Introduction
A mixed model with random effects was chosen for this multifactor experiment, and analyzed using the limma package in R. This package implements a linear modeling approach and empiracal Bayes statistics. The limma package with the voom method estimates the mean-variance relationship of the log-counts, generates a precision weight for each observation and enters these into the limma empirical Bayes analysis pipeline.
In this model, clade (levels = Clade1, Clade2, Clade3), physiology (levels = Marine, Freshwater), and experimental condition (levels = 15ppt, 0.2ppt) are fixed effects while species (levels = 14) is considered a random effect.
The raw counts file, generated with the NumReads from the salmon (version 0.12.0) quantification tool and summarized with the tximport Bioconductor package (version 1.10.1) in R, can be downloaded from an osf repository with this link, then imported into the R framework.
Samples from species with low numbers of replicates were dropped from the raw counts table (F. zebrinus, F. nottii, F. sciadicus). The raw counts table has the following dimensions (genes x samples).
#dim(design)
#[1] 5 81
dim(counts)
[1] 30466 81
Sample Design Matrix
A matrix was generated using the fixed effects with the following model:
~0 + physiology*condition*clade
The random effect of species will be taken into account later.
Filtering and Normalization
Genes with low expression across samples were dropped from the analysis using a conservative approach. The function filterByExpr was used on the raw counts matrix. For each condition_physiology group (regardless of species), each sample must have a minium count of 10, and a group minium total count of 100. This reduced the counts table to the following dimensions (genes x samples):
gene.names<-rownames(counts)
counts<-as.matrix(as.data.frame(sapply(counts, as.numeric)))
rownames(counts)<-gene.names
#class(counts)
keep<-filterByExpr(counts,design = design,group=condition_physiology,min.count = 10, min.total.count = 100)
counts.filt <- counts[keep,]
dim(counts.filt)
#write.csv(counts.filt,"../../../21k_counts_filt_30April2019.csv")
Genes of Interest
After filtration, we will check the counts matrix for the presence of several genes of interest. These genes have demonstrated responsiveness to salinity change from past studies.
| zymogen granule membrane protein 16 |
Funhe2EKm029929 |
ENSFHEP00000007220.1 |
|
| zymogen granule membrane protein 16 |
Funhe2EKm029931 |
ENSFHEP00000025841 |
|
| solute carrier family 12 member 3-like (removed) |
Funhe2EKm006896 |
ENSFHEP00000009214 |
|
| chloride channel, voltage-sensitive 2 (clcn2), transcript variant X2 (removed) |
Funhe2EKm024148 |
ENSFHEP00000019510 |
|
| ATP-sensitive inward rectifier potassium channel 1 |
Funhe2EKm001965 |
ENSFHEP00000015383 |
|
| inward rectifier potassium channel 2 |
Funhe2EKm023780 |
ENSFHEP00000009753 |
|
| aquaporin-3 |
|
ENSFHEP00000006725 |
|
| cftr |
Funhe2EKm024501 |
ENSFHEP00000008393 |
|
| polyamine-modulated factor 1-like |
Funhe2EKm031049 |
ENSFHEP00000013324 |
|
| sodium/potassium/calcium exchanger 2 |
Funhe2EKm025497 |
ENSFHEP00000034177 |
|
| septin-2B isoform X2 |
|
ENSFHEP00000015765 |
|
| CLOCK-interacting pacemaker-like |
Funhe2EKm026846 |
ENSFHEP00000017303 |
|
| vasopressin V2 receptor-like |
Funhe2EKm026721 |
ENSFHEP00000000036 |
|
| sodium/potassium-transporting ATPase subunit beta-1-interacting protein 1 |
Funhe2EKm001174 |
ENSFHEP00000031108 |
|
| septin-2 |
Funhe2EKm012182 |
ENSFHEP00000016853 |
|
| otopetrin-2 |
Funhe2EKm035427 |
ENSFHEP00000026411 |
|
| claudin 8 |
Funhe2EKm037718 |
ENSFHEP00000006282 |
|
| claudin 4 |
Funhe2EKm007149 |
ENSFHEP00000003908 |
|
If the Ensembl ID displays below, the gene is present in the whole data set and has not been filtered.
# ---------------------------
# Andrew Whitehead's genes of interest:
# ---------------------------
# zymogen granule membrane protein 16
# Funhe2EKm029929
# ENSFHEP00000007220.1
countsfilt <- counts.filt
countsfilt$row <- rownames(countsfilt)
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000007220.1"]
goi
# zymogen granule membrane protein 16
# Funhe2EKm029931
# ENSFHEP00000025841
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000025841"]
goi
# solute carrier family 12 member 3-like (removed)
# Funhe2EKm006896
# ENSFHEP00000009214
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000009214"]
goi
# chloride channel, voltage-sensitive 2 (clcn2), transcript variant X2 (removed)
# Funhe2EKm024148
# ENSFHEP00000019510
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000019510"]
goi
# ATP-sensitive inward rectifier potassium channel 1
# Funhe2EKm001965
# ENSFHEP00000015383
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000015383"]
goi
# inward rectifier potassium channel 2
# Funhe2EKm023780
# ENSFHEP00000009753
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000009753"]
# --------------------------------
# other salinity genes of interest
# --------------------------------
# ============================================
# aquaporin-3
# ENSFHEP00000006725
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000006725"]
goi
# cftr
# Funhe2EKm024501
# ENSFHEP00000008393
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000008393"]
goi
# polyamine-modulated factor 1-like
# Funhe2EKm031049
# ENSFHEP00000013324
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000013324"]
goi
# sodium/potassium/calcium exchanger 2
# ENSFHEP00000034177
# Funhe2EKm025497
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000034177"]
goi
# septin-2B isoform X2
# ENSFHEP00000015765
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000015765"]
goi
# CLOCK-interacting pacemaker-like
# ENSFHEP00000017303
# Funhe2EKm026846
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000017303"]
goi
# vasopressin V2 receptor-like
# Funhe2EKm026721
# ENSFHEP00000000036
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000000036"]
goi
# sodium/potassium-transporting ATPase subunit beta-1-interacting protein 1
# ENSFHEP00000031108
# Funhe2EKm001174
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000031108"]
goi
# septin-2
# Funhe2EKm012182
# ENSFHEP00000016853
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000016853"]
goi
# otopetrin-2
# Funhe2EKm035427
# ENSFHEP00000026411
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000026411"]
goi
# claudin 8
# Funhe2EKm037718
# ENSFHEP00000006282
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000006282"]
goi
# claudin 4
# ENSFHEP00000003908
# Funhe2EKm007149
goi <- countsfilt$row[countsfilt$row == "ENSFHEP00000003908"]
goi
all_goi<-c("ENSFHEP00000007220.1","ENSFHEP00000025841","ENSFHEP00000019510",
"ENSFHEP00000015383","ENSFHEP00000009753","ENSFHEP00000006725","ENSFHEP00000008393",
"ENSFHEP00000013324","ENSFHEP00000001609","ENSFHEP00000013324","ENSFHEP00000034177",
"ENSFHEP00000015765","ENSFHEP00000017303","ENSFHEP00000000036","ENSFHEP00000031108",
"ENSFHEP00000016853","ENSFHEP00000003908")
Exploratory Plots
Log counts before normalization:
# log counts before DE
boxplot(log(counts.filt+1), las = 2, main = "")
Log counts after cpm normalization
# ---------------
# DE analysis
# ---------------
genes = DGEList(count = counts.filt, group = condition_physiology_clade)
genes = calcNormFactors( genes )
# write normalized counts
dir <- "~/Documents/UCDavis/Whitehead/"
tmp <- as.data.frame(cpm(genes))
tmp$Ensembl <- rownames(tmp)
tmp <- dplyr::select(tmp, Ensembl, everything())
write.csv(tmp, file = file.path(dir, "normalized_counts.csv"), quote = F, row.names = F)
vobj = voom( genes, design, plot=TRUE)
lcpm <- cpm(genes$counts, log = TRUE)
# log counts after DE
boxplot(lcpm, las = 2, main = "")
plot(colSums(t(lcpm)))
Voom weights:
vwts <- voomWithQualityWeights(genes, design=design, normalization="quantile", plot=TRUE)
The random effects of species are taken into account with the duplicateCorrelation function, which estimates the correlation between species. This reflects the between-species variability. The higher the correlation (0-1.0), the higher the variability between species.
corfit <- duplicateCorrelation(vobj,design,block=ExpDesign$species)
corfit$consensus
#[1] 0.751381
Individuals clustered by overall expression

Individuals clustered by Top 100 genes

Individuals clustered by top 50 gene expression

PCA for overall expression

Contrasts
After running the lmFit function, which fits the linear model for each gene in the matrix and takes the random effects correlation into account, the resulting linear model fit is then used to compute the estimated coefficients and standard errors for a given set of contrasts:
fitRan <- lmFit(vobj,design,block=ExpDesign$species,correlation=corfit$consensus)
#colnames(coef(fitRan))
y <- rnorm(n = nrow(design))
dummy.mod <- lm(y ~ physiology*condition*clade,
data = ExpDesign)
pairs <- pairs(emmeans(dummy.mod, ~condition|clade*physiology ), reverse = T)
contrast.matrix <- pairs@linfct
tmp <- pairs@grid
contrasts <- gsub(" ", "", tmp$contrast)
contrasts <- gsub("-", "_v_", contrasts)
contrasts <- paste0(contrasts, "_", tmp$clade, "_", tmp$physiology)
rownames(contrast.matrix) <- contrasts
contrasts
[1] "15_ppt_v_0.2_ppt_Clade1_FW" "15_ppt_v_0.2_ppt_Clade2_FW" "15_ppt_v_0.2_ppt_Clade3_FW"
[4] "15_ppt_v_0.2_ppt_Clade1_M" "15_ppt_v_0.2_ppt_Clade2_M" "15_ppt_v_0.2_ppt_Clade3_M"
tables <- lapply(contrasts, function(contr){
print(contr)
cm <- contrast.matrix[contr,]
ph <- sapply(strsplit(as.character(contr), "_"), tail, 1)
cl <- sapply(strsplit(as.character(contr), "_"), tail, 2)
tmp <- contrasts.fit(fitRan, contrasts = cm)
tmp <- eBayes(tmp)
tmp2 <- topTable(tmp, n = Inf, sort.by = "P")
tmp3 <- tmp2
tmp3$row <- rownames(tmp3)
tmp3 <- merge(ann,tmp3,by.x = "ensembl_peptide_id", by.y = "row", all = TRUE)
tmp3 <- tmp3[order(tmp3$adj.P.Val),]
filename <- paste0(contr, ".csv")
#write.csv(tmp2, file = file.path(dir, filename),quote = F)
tab <- kable(head(tmp2, 20), digits = 5, row.names = F)
header1 <- 6
names(header1) <- paste0("Top 20 genes for ", contr)
header2 <- 6
names(header2) <- paste0("Number of genes with adjusted P < 0.05 = ", length(which(tmp2$adj.P.Val < 0.05)))
header3 <- 6
names(header3) <- paste0("Output file is ", filename)
tab <- tab %>% add_header_above(header3, align = 'l') %>% add_header_above(header2, align = 'l') %>% add_header_above(header1, align = 'l', font_size = "larger", bold = T)
tab <- tab %>% kable_styling()
return(list(tab, nump = length(which(tmp2$adj.P.Val < 0.05))))
}
)
[1] "15_ppt_v_0.2_ppt_Clade1_FW"
row names of contrasts don't match col names of coefficients
[1] "15_ppt_v_0.2_ppt_Clade2_FW"
row names of contrasts don't match col names of coefficients
[1] "15_ppt_v_0.2_ppt_Clade3_FW"
row names of contrasts don't match col names of coefficients
[1] "15_ppt_v_0.2_ppt_Clade1_M"
row names of contrasts don't match col names of coefficients
[1] "15_ppt_v_0.2_ppt_Clade2_M"
row names of contrasts don't match col names of coefficients
[1] "15_ppt_v_0.2_ppt_Clade3_M"
row names of contrasts don't match col names of coefficients
Three-way contrasts
The number of genes significant for the three-way interaction of condition:physiology:clade:
sigps <- unlist(lapply(tables, function(x)x[[2]]))
sumtab <- data.frame(Comparison = contrasts, `Number of genes with adjusted P < 0.05` = sigps,
check.names = F)
kable(sumtab, align = 'c') %>% kable_styling() %>%
add_header_above(c("Overview of results" = 2), font_size = "larger", bold = T, align = "l")
Two-way contrasts
These genes demonstrate a conserved response to experimental condition across M or FW physiologies, regardless of clade.
y <- rnorm(n = nrow(design))
dummy.mod <- lm(y ~ physiology*condition*clade,
data = ExpDesign)
pairs <- pairs(emmeans(dummy.mod, ~condition|physiology ), reverse = T)
contrast.matrix <- pairs@linfct
tmp <- pairs@grid
contrasts <- gsub(" ", "", tmp$contrast)
contrasts <- gsub("-", "_v_", contrasts)
contrasts <- paste0(contrasts, "_", tmp$physiology)
rownames(contrast.matrix) <- contrasts
contrasts
tables <- lapply(contrasts, function(contr){
print(contr)
cm <- contrast.matrix[contr,]
ph <- sapply(strsplit(as.character(contr), "_"), tail, 1)
cl <- sapply(strsplit(as.character(contr), "_"), tail, 2)
tmp <- contrasts.fit(fitRan, contrasts = cm)
tmp <- eBayes(tmp)
tmp2 <- topTable(tmp, n = Inf, sort.by = "P")
#tmp3 <- tmp2
#tmp3$row <- rownames(tmp3)
#tmp3 <- merge(ann,tmp3,by.x = "ensembl_peptide_id", by.y = "row", all = TRUE)
#tmp3 <- tmp3[order(tmp3$adj.P.Val),]
filename <- paste0(contr, ".csv")
#write.csv(tmp2, file = file.path(dir, filename),quote = F)
tab <- kable(head(tmp2, 20), digits = 5, row.names = F)
header1 <- 6
names(header1) <- paste0("Top 20 genes for ", contr)
header2 <- 6
names(header2) <- paste0("Number of genes with adjusted P < 0.05 = ", length(which(tmp2$adj.P.Val < 0.05)))
header3 <- 6
names(header3) <- paste0("Output file is ", filename)
tab <- tab %>% add_header_above(header3, align = 'l') %>% add_header_above(header2, align = 'l') %>% add_header_above(header1, align = 'l', font_size = "larger", bold = T)
tab <- tab %>% kable_styling()
return(list(tab, nump = length(which(tmp2$adj.P.Val < 0.05))))
}
)
Heatmaps
Marine-Clade 1 (three-way) response
rld <- log2(mean_norm_counts_ordered_M_Clade1_sig+1)
geneDists <- dist(mean_norm_counts_ordered_M_Clade1_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Freshwater-Clade 1 (three-way) response
rld <- log2(mean_norm_counts_ordered_FW_Clade1_sig+1)
geneDists <- dist(mean_norm_counts_ordered_FW_Clade1_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Marine-Clade 2 (three-way) response
rld <- log2(mean_norm_counts_ordered_M_Clade2_sig+1)
geneDists <- dist(mean_norm_counts_ordered_M_Clade2_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Freshwater-Clade 2 (three-way) response
rld <- log2(mean_norm_counts_ordered_FW_Clade2_sig+1)
geneDists <- dist(mean_norm_counts_ordered_FW_Clade2_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Marine-Clade 3 (three-way) response
rld <- log2(mean_norm_counts_ordered_M_Clade3_sig+1)
geneDists <- dist(mean_norm_counts_ordered_M_Clade3_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Freshwater-Clade 3 (three-way) response
rld <- log2(mean_norm_counts_ordered_FW_Clade3_sig+1)
geneDists <- dist(mean_norm_counts_ordered_FW_Clade3_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Marine physiology (two-way) conserved response
rld <- log2(mean_norm_counts_ordered_M_sig+1)
geneDists <- dist(mean_norm_counts_ordered_M_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
Freshwater physiology (two-way) conserved response
rld <- log2(mean_norm_counts_ordered_FW_sig+1)
geneDists <- dist(mean_norm_counts_ordered_FW_sig)
df <- data.frame(ph,cl, condition,stringsAsFactors=FALSE)
rownames(df) <- colnames(rld)
pheatmap(rld, show_rownames=FALSE,
clustering_distance_rows = geneDists, cluster_cols= FALSE,annotation_col=df)
sessionInfo()
LS0tCnRpdGxlOiAiREVhbmFseXNpc19rZmlzaF9vc21vdGljIgphdXRob3I6ICJMaXNhIEpvaG5zb24iCmRhdGU6ICdgciBTeXMuRGF0ZSgpYCcKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvbGxhcHNlZDogbm8KICAgIGRmX3ByaW50OiBwYWdlZAogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRoZW1lOiBjZXJ1bGVhbgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNQogICAgdG9jX2Zsb2F0OiB5ZXMKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNQotLS0KCiMgSW50cm9kdWN0aW9uCgpBIG1peGVkIG1vZGVsIHdpdGggcmFuZG9tIGVmZmVjdHMgd2FzIGNob3NlbiBmb3IgdGhpcyBtdWx0aWZhY3RvciBleHBlcmltZW50LCBhbmQgYW5hbHl6ZWQgdXNpbmcgdGhlIGBsaW1tYWAgcGFja2FnZSBpbiBSLiBUaGlzIHBhY2thZ2UgaW1wbGVtZW50cyBhIGxpbmVhciBtb2RlbGluZyBhcHByb2FjaCBhbmQgZW1waXJhY2FsIEJheWVzIHN0YXRpc3RpY3MuIFRoZSBgbGltbWFgIHBhY2thZ2Ugd2l0aCB0aGUgYHZvb21gIG1ldGhvZCBlc3RpbWF0ZXMgdGhlIG1lYW4tdmFyaWFuY2UgcmVsYXRpb25zaGlwIG9mIHRoZSBsb2ctY291bnRzLCBnZW5lcmF0ZXMgYSBwcmVjaXNpb24gd2VpZ2h0IGZvciBlYWNoIG9ic2VydmF0aW9uIGFuZCBlbnRlcnMgdGhlc2UgaW50byB0aGUgbGltbWEgZW1waXJpY2FsIEJheWVzIGFuYWx5c2lzIHBpcGVsaW5lLgoKSW4gdGhpcyBtb2RlbCwgYGNsYWRlYCAobGV2ZWxzID0gQ2xhZGUxLCBDbGFkZTIsIENsYWRlMyksIGBwaHlzaW9sb2d5YCAobGV2ZWxzID0gTWFyaW5lLCBGcmVzaHdhdGVyKSwgYW5kIGV4cGVyaW1lbnRhbCBgY29uZGl0aW9uYCAobGV2ZWxzID0gMTVwcHQsIDAuMnBwdCkgYXJlIGZpeGVkIGVmZmVjdHMgd2hpbGUgYHNwZWNpZXNgIChsZXZlbHMgPSAxNCkgaXMgY29uc2lkZXJlZCBhIHJhbmRvbSBlZmZlY3QuCgpgYGB7ciBMb2FkUGFja2FnZXMsIHJlc3VsdHM9J2hpZGUnLCBpbmNsdWRlPUZBTFNFfQoKIyBJbnN0YWxsIGZ1bmN0aW9uIGZvciBwYWNrYWdlcyAgICAKcGFja2FnZXM8LWZ1bmN0aW9uKHgpewogIHg8LWFzLmNoYXJhY3RlcihtYXRjaC5jYWxsKClbWzJdXSkKICBpZiAoIXJlcXVpcmUoeCxjaGFyYWN0ZXIub25seT1UUlVFKSl7CiAgICBpbnN0YWxsLnBhY2thZ2VzKHBrZ3M9eCxyZXBvcz0iaHR0cDovL2NyYW4uci1wcm9qZWN0Lm9yZyIpCiAgICByZXF1aXJlKHgsY2hhcmFjdGVyLm9ubHk9VFJVRSkKICB9Cn0KCmJpb2NvbmR1Y3RvcnMgPC0gZnVuY3Rpb24oeCl7CiAgICB4PC0gYXMuY2hhcmFjdGVyKG1hdGNoLmNhbGwoKVtbMl1dKQogICAgaWYgKCFyZXF1aXJlKHgsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkpewogICAgICBzb3VyY2UoImh0dHBzOi8vYmlvY29uZHVjdG9yLm9yZy9iaW9jTGl0ZS5SIikKICAgICAgYmlvY0xpdGUocGtncz14KQogICAgICByZXF1aXJlKHgsIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkKICAgIH0KfQoKcGFja2FnZXMoTUFTUykKcGFja2FnZXMoZ2dwbG90MikKcGFja2FnZXMoZ3Rvb2xzKQpwYWNrYWdlcyhwaGVhdG1hcCkKcGFja2FnZXMoY293cGxvdCkKcGFja2FnZXMoUkNvbG9yQnJld2VyKQpwYWNrYWdlcyhkcGx5cikKcGFja2FnZXModGlkeXIpCnBhY2thZ2VzKGtuaXRyKQpwYWNrYWdlcyhnZ3JlcGVsKQpiaW9jb25kdWN0b3JzKERFU2VxMikKYmlvY29uZHVjdG9ycyhsaW1tYSkKYmlvY29uZHVjdG9ycygnZWRnZVInKQpwYWNrYWdlcyhncGxvdHMpCnBhY2thZ2VzKGxhdHRpY2UpCnBhY2thZ2VzKCJ2c24iKQpiaW9jb25kdWN0b3JzKGJpb21hUnQpCnBhY2thZ2VzKGthYmxlRXh0cmEpCnBhY2thZ2VzKHBoZWF0bWFwKQpwYWNrYWdlcygiU3VtbWFyaXplZEV4cGVyaW1lbnQiKQpwYWNrYWdlcygiZW1tZWFucyIpCnBhY2thZ2VzKGRhdGEudGFibGUpCmBgYAoKVGhlIHJhdyBjb3VudHMgZmlsZSwgZ2VuZXJhdGVkIHdpdGggdGhlIGBOdW1SZWFkc2AgZnJvbSB0aGUgc2FsbW9uICh2ZXJzaW9uIDAuMTIuMCkgcXVhbnRpZmljYXRpb24gdG9vbCBhbmQgc3VtbWFyaXplZCB3aXRoIHRoZSB0eGltcG9ydCBCaW9jb25kdWN0b3IgcGFja2FnZSAodmVyc2lvbiAxLjEwLjEpIGluIFIsIGNhbiBiZSBkb3dubG9hZGVkIGZyb20gYW4gW29zZiByZXBvc2l0b3J5XShodHRwczovL29zZi5pby9tNHhlZy8pIHdpdGggdGhpcyBbbGlua10oaHR0cHM6Ly9vc2YuaW8vN3ZwMzgvZG93bmxvYWQpLCB0aGVuIGltcG9ydGVkIGludG8gdGhlIFIgZnJhbWV3b3JrLgoKYGBge3IgbG9hZGZpbGVzLCByZXN1bHRzPSdoaWRlJywgaW5jbHVkZT1GQUxTRX0KIyBUaGlzIGlzIHRoZSBjb3VudHMgd2l0aCBFeHBlcmltZW50YWwgRGVzaWduIEluZm8gaW4gdGhlIGxhc3QgNSByb3dzCgpzZXR3ZCgifi9Eb2N1bWVudHMvVUNEYXZpcy9XaGl0ZWhlYWQvUk5Bc2VxXzE1a2lsbGlmaXNoL0RFX3NjcmlwdHMvbGltbWEiKQppZighZmlsZS5leGlzdHMoJ34vRG9jdW1lbnRzL1VDRGF2aXMvV2hpdGVoZWFkL0Vuc2VtYmxfc3BlY2llc19jb3VudHNfZGVzaWduZmFjdG9ycy5jc3YnKSl7CiAgZG93bmxvYWQuZmlsZSgiaHR0cHM6Ly9vc2YuaW8vN3ZwMzgvZG93bmxvYWQiLCdFbnNlbWJsX3NwZWNpZXNfY291bnRzX2Rlc2lnbmZhY3RvcnMuY3N2JykKfQoKY291bnRzX2Rlc2lnbiA8LSByZWFkLmNzdigifi9Eb2N1bWVudHMvVUNEYXZpcy9XaGl0ZWhlYWQvRW5zZW1ibF9zcGVjaWVzX2NvdW50c19kZXNpZ25mYWN0b3JzLmNzdiIsc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKYGBgCgpTYW1wbGVzIGZyb20gc3BlY2llcyB3aXRoIGxvdyBudW1iZXJzIG9mIHJlcGxpY2F0ZXMgd2VyZSBkcm9wcGVkIGZyb20gdGhlIHJhdyBjb3VudHMgdGFibGUgKCpGLiB6ZWJyaW51cyosICpGLiBub3R0aWkqLCAqRi4gc2NpYWRpY3VzKikuIFRoZSByYXcgY291bnRzIHRhYmxlIGhhcyB0aGUgZm9sbG93aW5nIGRpbWVuc2lvbnMgKGdlbmVzIHggc2FtcGxlcykuIAoKYGBge3IgZHJvcHNhbXBsZXMscmVzdWx0cz0nc2hvdyd9CgojZGltKGNvdW50c19kZXNpZ24pCiNbMV0gMzA0NzEgICAxMzAKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBGb3JtYXQgZGVzaWduIGFuZCBjb3VudHMgbWF0cml4CiMgRHJvcCBjb2x1bW5zIHdpdGggbm8gZGF0YQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpkZXNpZ24gPC0gY291bnRzX2Rlc2lnbltjb3VudHNfZGVzaWduJEVuc2VtYmwgPT0gJ0VtcHR5JyxdCiNkZXNpZ24kdHlwZSA8LSBjKCJzcGVjaWVzIiwibmF0aXZlX3NhbGluaXR5IiwiY2xhZGUiLCJncm91cCIsImNvbmRpdGlvbiIpCmRyb3BzIDwtIGMoIlgiLCJFbnNlbWJsIiwKICAgICAgICAgICAiRl96ZWJyaW51c19CV18xLnF1YW50IiwiRl96ZWJyaW51c19CV18yLnF1YW50IiwKICAgICAgICAgICAiRl96ZWJyaW51c19GV18xLnF1YW50IiwiRl96ZWJyaW51c19GV18yLnF1YW50IiwKICAgICAgICAgICAiRl9ub3R0aV9GV18xLnF1YW50IiwiRl9ub3R0aV9GV18yLnF1YW50IiwKICAgICAgICAgICAiRl9zY2lhZGljdXNfQldfMS5xdWFudCIsIkZfc2NpYWRpY3VzX0ZXXzEucXVhbnQiLCJGX3NjaWFkaWN1c19GV18yLnF1YW50IikKdHJhbnNmZXJfZHJvcHMgPC0gYygiRl9zY2lhZGljdXNfdHJhbnNmZXJfMS5xdWFudCIsIkZfcmF0aGJ1bmlfdHJhbnNmZXJfMS5xdWFudCIsIkZfcmF0aGJ1bmlfdHJhbnNmZXJfMi5xdWFudCIsIkZfcmF0aGJ1bmlfdHJhbnNmZXJfMy5xdWFudCIsCiAgICAgICAgICAgICAgICAgICAgIkZfZ3JhbmRpc190cmFuc2Zlcl8xLnF1YW50IiwiRl9ncmFuZGlzX3RyYW5zZmVyXzIucXVhbnQiLCJGX2dyYW5kaXNfdHJhbnNmZXJfMy5xdWFudCIsCiAgICAgICAgICAgICAgICAgICAgIkZfbm90YXR1c190cmFuc2Zlcl8xLnF1YW50IiwiRl9ub3RhdHVzX3RyYW5zZmVyXzIucXVhbnQiLCJGX25vdGF0dXNfdHJhbnNmZXJfMy5xdWFudCIsCiAgICAgICAgICAgICAgICAgICAgIkZfcGFydmFwaW5pc190cmFuc2Zlcl8xLnF1YW50IiwiRl9wYXJ2YXBpbmlzX3RyYW5zZmVyXzIucXVhbnQiLAogICAgICAgICAgICAgICAgICAgICJMX2dvb2RlaV90cmFuc2Zlcl8xLnF1YW50IiwiTF9nb29kZWlfdHJhbnNmZXJfMi5xdWFudCIsIkxfZ29vZGVpX3RyYW5zZmVyXzMucXVhbnQiLAogICAgICAgICAgICAgICAgICAgICJGX29saXZhY2VvdXNfdHJhbnNmZXJfMS5xdWFudCIsIkZfb2xpdmFjZW91c190cmFuc2Zlcl8yLnF1YW50IiwKICAgICAgICAgICAgICAgICAgICAiTF9wYXJ2YV90cmFuc2Zlcl8xLnF1YW50IiwiTF9wYXJ2YV90cmFuc2Zlcl8yLnF1YW50IiwiTF9wYXJ2YV90cmFuc2Zlcl8zLnF1YW50IiwKICAgICAgICAgICAgICAgICAgICAiRl9oZXRlcm9jbGl0dXNNRFBQX3RyYW5zZmVyXzEucXVhbnQiLCJGX2hldGVyb2NsaXR1c01EUFBfdHJhbnNmZXJfMi5xdWFudCIsIkZfaGV0ZXJvY2xpdHVzTURQUF90cmFuc2Zlcl8zLnF1YW50IiwKICAgICAgICAgICAgICAgICAgICAiRl9zaW1pbGlzX3RyYW5zZmVyXzEucXVhbnQiLCJGX3NpbWlsaXNfdHJhbnNmZXJfMi5xdWFudCIsIkZfc2ltaWxpc190cmFuc2Zlcl8zLnF1YW50IiwKICAgICAgICAgICAgICAgICAgICAiRl9kaWFwaGFudXNfdHJhbnNmZXJfMS5xdWFudCIsIkZfZGlhcGhhbnVzX3RyYW5zZmVyXzIucXVhbnQiLAogICAgICAgICAgICAgICAgICAgICJGX2Nocnlzb3R1c190cmFuc2Zlcl8xLnF1YW50IiwiRl9jaHJ5c290dXNfdHJhbnNmZXJfMi5xdWFudCIsCiAgICAgICAgICAgICAgICAgICAgIkFfeGVuaWNhX3RyYW5zZmVyXzEucXVhbnQiLCJBX3hlbmljYV90cmFuc2Zlcl8yLnF1YW50IiwiQV94ZW5pY2FfdHJhbnNmZXJfMy5xdWFudCIgLAogICAgICAgICAgICAgICAgICAgICJGX2NhdGFuYXR1c190cmFuc2Zlcl8xLnF1YW50IiwiRl9jYXRhbmF0dXNfdHJhbnNmZXJfMi5xdWFudCIsCiAgICAgICAgICAgICAgICAgICAgIkZfaGV0ZXJvY2xpdHVzTURQTF90cmFuc2Zlcl8xLnF1YW50IiwiRl9oZXRlcm9jbGl0dXNNRFBMX3RyYW5zZmVyXzIucXVhbnQiLCJGX2hldGVyb2NsaXR1c01EUExfdHJhbnNmZXJfMy5xdWFudCIpCmNvdW50czwtY291bnRzX2Rlc2lnblshY291bnRzX2Rlc2lnbiRFbnNlbWJsID09ICdFbXB0eScsXQpyb3duYW1lcyhjb3VudHMpPC1jb3VudHMkRW5zZW1ibApkZXNpZ24gPC0gZGVzaWduWyAsICEobmFtZXMoZGVzaWduKSAlaW4lIGRyb3BzKV0KY291bnRzIDwtIGNvdW50c1sgLCAhKG5hbWVzKGNvdW50cykgJWluJSBkcm9wcyldCmRlc2lnbiA8LSBkZXNpZ25bICwgIShuYW1lcyhkZXNpZ24pICVpbiUgdHJhbnNmZXJfZHJvcHMpXQpjb3VudHMgPC0gY291bnRzWyAsICEobmFtZXMoY291bnRzKSAlaW4lIHRyYW5zZmVyX2Ryb3BzKV0KI2RpbShkZXNpZ24pCiNbMV0gIDUgODEKZGltKGNvdW50cykKZ2VuZS5uYW1lczwtcm93bmFtZXMoY291bnRzKQpkZXNpZ25bXSA8LSBsYXBwbHkoIGRlc2lnbiwgZmFjdG9yKQpgYGAKCiMgU2FtcGxlIERlc2lnbiBNYXRyaXgKCkEgbWF0cml4IHdhcyBnZW5lcmF0ZWQgdXNpbmcgdGhlIGZpeGVkIGVmZmVjdHMgd2l0aCB0aGUgZm9sbG93aW5nIG1vZGVsOiAKCmBgYAp+MCArIHBoeXNpb2xvZ3kqY29uZGl0aW9uKmNsYWRlCmBgYApUaGUgcmFuZG9tIGVmZmVjdCBvZiBgc3BlY2llc2Agd2lsbCBiZSB0YWtlbiBpbnRvIGFjY291bnQgbGF0ZXIuCgpgYGB7ciBkZXNpZ25pbmZvLHJlc3VsdHM9J3Nob3cnfQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLQojIGRlc2lnbiBjYXRlb2dvcmllcwojIC0tLS0tLS0tLS0tLS0tLS0tLS0tCgpzcGVjaWVzPC1hcy5jaGFyYWN0ZXIodW5saXN0KGRlc2lnblsxLF0pKQpwaHlzaW9sb2d5PC1hcy5jaGFyYWN0ZXIodW5saXN0KGRlc2lnblsyLF0pKQpjbGFkZTwtYXMuY2hhcmFjdGVyKHVubGlzdChkZXNpZ25bMyxdKSkKY29uZGl0aW9uPC1hcy5jaGFyYWN0ZXIodW5saXN0KGRlc2lnbls1LF0pKQpjb25kaXRpb25fcGh5c2lvbG9neTwtYXMudmVjdG9yKHBhc3RlKGNvbmRpdGlvbixwaHlzaW9sb2d5LHNlcD0iLiIpKQpjb25kaXRpb25fcGh5c2lvbG9neV9jbGFkZSA8LSBhcy52ZWN0b3IocGFzdGUoY29uZGl0aW9uX3BoeXNpb2xvZ3ksY2xhZGUsc2VwPSIuIikpCmNvbmRpdGlvbl9waHlzaW9sb2d5X2NsYWRlIDwtIGFzLnZlY3RvcihwYXN0ZSgiZ3JvdXAiLGNvbmRpdGlvbl9waHlzaW9sb2d5X2NsYWRlLHNlcD0iIikpCmNvbHM8LWNvbG5hbWVzKGNvdW50cykKRXhwRGVzaWduIDwtIGRhdGEuZnJhbWUocm93Lm5hbWVzPWNvbHMsCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbmRpdGlvbj1jb25kaXRpb24sCiAgICAgICAgICAgICAgICAgICAgICAgIHBoeXNpb2xvZ3kgPSBwaHlzaW9sb2d5LAogICAgICAgICAgICAgICAgICAgICAgICBjbGFkZSA9IGNsYWRlLAogICAgICAgICAgICAgICAgICAgICAgICBzcGVjaWVzID0gc3BlY2llcywKICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlPWNvbHMpCkV4cERlc2lnbgpkZXNpZ24gPSBtb2RlbC5tYXRyaXgoIH4wICsgcGh5c2lvbG9neSpjb25kaXRpb24qY2xhZGUsIEV4cERlc2lnbikKY29sbmFtZXMoZGVzaWduKQojIGNoZWNrIHJhbmsgb2YgbWF0cml4CiNNYXRyaXg6OnJhbmtNYXRyaXgoIGRlc2lnbiApCiNkaW0oZGVzaWduKQpgYGAKCiMgRmlsdGVyaW5nIGFuZCBOb3JtYWxpemF0aW9uCgpHZW5lcyB3aXRoIGxvdyBleHByZXNzaW9uIGFjcm9zcyBzYW1wbGVzIHdlcmUgZHJvcHBlZCBmcm9tIHRoZSBhbmFseXNpcyB1c2luZyBhIGNvbnNlcnZhdGl2ZSBhcHByb2FjaC4gVGhlIGZ1bmN0aW9uIGBmaWx0ZXJCeUV4cHJgIHdhcyB1c2VkIG9uIHRoZSByYXcgY291bnRzIG1hdHJpeC4gRm9yIGVhY2ggYGNvbmRpdGlvbl9waHlzaW9sb2d5YCBncm91cCAocmVnYXJkbGVzcyBvZiBzcGVjaWVzKSwgZWFjaCBzYW1wbGUgbXVzdCBoYXZlIGEgbWluaXVtIGNvdW50IG9mIDEwLCBhbmQgYSBncm91cCBtaW5pdW0gdG90YWwgY291bnQgb2YgMTAwLiBUaGlzIHJlZHVjZWQgdGhlIGNvdW50cyB0YWJsZSB0byB0aGUgZm9sbG93aW5nIGRpbWVuc2lvbnMgKGdlbmVzIHggc2FtcGxlcyk6CgpgYGB7ciBmaWx0LCByZXN1bHRzPSJzaG93In0KCmdlbmUubmFtZXM8LXJvd25hbWVzKGNvdW50cykKY291bnRzPC1hcy5tYXRyaXgoYXMuZGF0YS5mcmFtZShzYXBwbHkoY291bnRzLCBhcy5udW1lcmljKSkpCnJvd25hbWVzKGNvdW50cyk8LWdlbmUubmFtZXMKI2NsYXNzKGNvdW50cykKCmtlZXA8LWZpbHRlckJ5RXhwcihjb3VudHMsZGVzaWduID0gZGVzaWduLGdyb3VwPWNvbmRpdGlvbl9waHlzaW9sb2d5LG1pbi5jb3VudCA9IDEwLCBtaW4udG90YWwuY291bnQgPSAxMDApCmNvdW50cy5maWx0IDwtIGNvdW50c1trZWVwLF0KZGltKGNvdW50cy5maWx0KQojd3JpdGUuY3N2KGNvdW50cy5maWx0LCIuLi8uLi8uLi8yMWtfY291bnRzX2ZpbHRfMzBBcHJpbDIwMTkuY3N2IikKYGBgCgojIEdlbmVzIG9mIEludGVyZXN0CgpBZnRlciBmaWx0cmF0aW9uLCB3ZSB3aWxsIGNoZWNrIHRoZSBjb3VudHMgbWF0cml4IGZvciB0aGUgcHJlc2VuY2Ugb2Ygc2V2ZXJhbCBnZW5lcyBvZiBpbnRlcmVzdC4gVGhlc2UgZ2VuZXMgaGF2ZSBkZW1vbnN0cmF0ZWQgcmVzcG9uc2l2ZW5lc3MgdG8gc2FsaW5pdHkgY2hhbmdlIGZyb20gcGFzdCBzdHVkaWVzLgoKfCBnZW5lICB8IEZ1bmhlICB8IEVuc2VtYmwgIHwgIAp8LS0tfC0tLXwtLS18LS0tfC0tLXwKfCB6eW1vZ2VuIGdyYW51bGUgbWVtYnJhbmUgcHJvdGVpbiAxNiAgfCBGdW5oZTJFS20wMjk5MjkgIHwgRU5TRkhFUDAwMDAwMDA3MjIwLjEgIHwgIAp8IHp5bW9nZW4gZ3JhbnVsZSBtZW1icmFuZSBwcm90ZWluIDE2ICB8IEZ1bmhlMkVLbTAyOTkzMSB8IEVOU0ZIRVAwMDAwMDAyNTg0MSAgfCAKfCBzb2x1dGUgY2FycmllciBmYW1pbHkgMTIgbWVtYmVyIDMtbGlrZSAocmVtb3ZlZCkgIHwgRnVuaGUyRUttMDA2ODk2ICB8ICBFTlNGSEVQMDAwMDAwMDkyMTQgfCAKfCBjaGxvcmlkZSBjaGFubmVsLCB2b2x0YWdlLXNlbnNpdGl2ZSAyIChjbGNuMiksIHRyYW5zY3JpcHQgdmFyaWFudCBYMiAocmVtb3ZlZCkgIHwgRnVuaGUyRUttMDI0MTQ4ICB8ICBFTlNGSEVQMDAwMDAwMTk1MTAgfCAKfCBBVFAtc2Vuc2l0aXZlIGlud2FyZCByZWN0aWZpZXIgcG90YXNzaXVtIGNoYW5uZWwgMSB8ICBGdW5oZTJFS20wMDE5NjUgfCBFTlNGSEVQMDAwMDAwMTUzODMgIHwgCnwgaW53YXJkIHJlY3RpZmllciBwb3Rhc3NpdW0gY2hhbm5lbCAyICB8ICBGdW5oZTJFS20wMjM3ODAgfCBFTlNGSEVQMDAwMDAwMDk3NTMgIHwgCnwgYXF1YXBvcmluLTMgIHwgICB8IEVOU0ZIRVAwMDAwMDAwNjcyNSAgfCAKfCBjZnRyICB8IEZ1bmhlMkVLbTAyNDUwMSAgfCBFTlNGSEVQMDAwMDAwMDgzOTMgIHwgCnwgcG9seWFtaW5lLW1vZHVsYXRlZCBmYWN0b3IgMS1saWtlIHwgRnVuaGUyRUttMDMxMDQ5ICB8IEVOU0ZIRVAwMDAwMDAxMzMyNCAgfCAKfCBzb2RpdW0vcG90YXNzaXVtL2NhbGNpdW0gZXhjaGFuZ2VyIDIgIHwgRnVuaGUyRUttMDI1NDk3IHwgRU5TRkhFUDAwMDAwMDM0MTc3IHwgCnwgc2VwdGluLTJCIGlzb2Zvcm0gWDIgIHwgICB8IEVOU0ZIRVAwMDAwMDAxNTc2NSAgfCAKfCBDTE9DSy1pbnRlcmFjdGluZyBwYWNlbWFrZXItbGlrZSAgfCBGdW5oZTJFS20wMjY4NDYgIHwgRU5TRkhFUDAwMDAwMDE3MzAzICB8IAp8IHZhc29wcmVzc2luIFYyIHJlY2VwdG9yLWxpa2UgIHwgRnVuaGUyRUttMDI2NzIxICB8IEVOU0ZIRVAwMDAwMDAwMDAzNiB8IAp8IHNvZGl1bS9wb3Rhc3NpdW0tdHJhbnNwb3J0aW5nIEFUUGFzZSBzdWJ1bml0IGJldGEtMS1pbnRlcmFjdGluZyBwcm90ZWluIDEgIHwgRnVuaGUyRUttMDAxMTc0ICB8IEVOU0ZIRVAwMDAwMDAzMTEwOCAgfCAKfCBzZXB0aW4tMiAgfCBGdW5oZTJFS20wMTIxODIgIHwgRU5TRkhFUDAwMDAwMDE2ODUzICB8IAp8IG90b3BldHJpbi0yICB8IEZ1bmhlMkVLbTAzNTQyNyAgfCBFTlNGSEVQMDAwMDAwMjY0MTEgIHwgCnwgY2xhdWRpbiA4ICB8IEZ1bmhlMkVLbTAzNzcxOCAgfCBFTlNGSEVQMDAwMDAwMDYyODIgIHwgCnwgY2xhdWRpbiA0ICB8IEZ1bmhlMkVLbTAwNzE0OSAgfCBFTlNGSEVQMDAwMDAwMDM5MDggIHwgCgpJZiB0aGUgRW5zZW1ibCBJRCBkaXNwbGF5cyBiZWxvdywgdGhlIGdlbmUgaXMgcHJlc2VudCBpbiB0aGUgd2hvbGUgZGF0YSBzZXQgYW5kIGhhcyBub3QgYmVlbiBmaWx0ZXJlZC4KCmBgYHtyIGdvaSwgcmVzdWx0cz0ic2hvdyJ9CgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIEFuZHJldyBXaGl0ZWhlYWQncyBnZW5lcyBvZiBpbnRlcmVzdDoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMgenltb2dlbiBncmFudWxlIG1lbWJyYW5lIHByb3RlaW4gMTYKIyBGdW5oZTJFS20wMjk5MjkKIyBFTlNGSEVQMDAwMDAwMDcyMjAuMQpjb3VudHNmaWx0IDwtIGNvdW50cy5maWx0CmNvdW50c2ZpbHQkcm93IDwtIHJvd25hbWVzKGNvdW50c2ZpbHQpCmdvaSA8LSBjb3VudHNmaWx0JHJvd1tjb3VudHNmaWx0JHJvdyA9PSAiRU5TRkhFUDAwMDAwMDA3MjIwLjEiXQpnb2kKIyB6eW1vZ2VuIGdyYW51bGUgbWVtYnJhbmUgcHJvdGVpbiAxNgojIEZ1bmhlMkVLbTAyOTkzMQojIEVOU0ZIRVAwMDAwMDAyNTg0MQpnb2kgPC0gY291bnRzZmlsdCRyb3dbY291bnRzZmlsdCRyb3cgPT0gIkVOU0ZIRVAwMDAwMDAyNTg0MSJdCmdvaQojIHNvbHV0ZSBjYXJyaWVyIGZhbWlseSAxMiBtZW1iZXIgMy1saWtlIChyZW1vdmVkKSAKIyBGdW5oZTJFS20wMDY4OTYKIyBFTlNGSEVQMDAwMDAwMDkyMTQKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMDkyMTQiXQpnb2kKIyBjaGxvcmlkZSBjaGFubmVsLCB2b2x0YWdlLXNlbnNpdGl2ZSAyIChjbGNuMiksIHRyYW5zY3JpcHQgdmFyaWFudCBYMiAocmVtb3ZlZCkKIyBGdW5oZTJFS20wMjQxNDgKIyBFTlNGSEVQMDAwMDAwMTk1MTAKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMTk1MTAiXQpnb2kKIyBBVFAtc2Vuc2l0aXZlIGlud2FyZCByZWN0aWZpZXIgcG90YXNzaXVtIGNoYW5uZWwgMSAKIyBGdW5oZTJFS20wMDE5NjUKIyBFTlNGSEVQMDAwMDAwMTUzODMKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMTUzODMiXQpnb2kKIyBpbndhcmQgcmVjdGlmaWVyIHBvdGFzc2l1bSBjaGFubmVsIDIKIyBGdW5oZTJFS20wMjM3ODAKIyBFTlNGSEVQMDAwMDAwMDk3NTMKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMDk3NTMiXQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIG90aGVyIHNhbGluaXR5IGdlbmVzIG9mIGludGVyZXN0CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIGFxdWFwb3Jpbi0zCiMgRU5TRkhFUDAwMDAwMDA2NzI1CmdvaSA8LSBjb3VudHNmaWx0JHJvd1tjb3VudHNmaWx0JHJvdyA9PSAiRU5TRkhFUDAwMDAwMDA2NzI1Il0KZ29pCiMgY2Z0cgojIEZ1bmhlMkVLbTAyNDUwMQojIEVOU0ZIRVAwMDAwMDAwODM5Mwpnb2kgPC0gY291bnRzZmlsdCRyb3dbY291bnRzZmlsdCRyb3cgPT0gIkVOU0ZIRVAwMDAwMDAwODM5MyJdCmdvaQojIHBvbHlhbWluZS1tb2R1bGF0ZWQgZmFjdG9yIDEtbGlrZQojIEZ1bmhlMkVLbTAzMTA0OQojIEVOU0ZIRVAwMDAwMDAxMzMyNApnb2kgPC0gY291bnRzZmlsdCRyb3dbY291bnRzZmlsdCRyb3cgPT0gIkVOU0ZIRVAwMDAwMDAxMzMyNCJdCmdvaQojIHNvZGl1bS9wb3Rhc3NpdW0vY2FsY2l1bSBleGNoYW5nZXIgMgojIEVOU0ZIRVAwMDAwMDAzNDE3NwojIEZ1bmhlMkVLbTAyNTQ5Nwpnb2kgPC0gY291bnRzZmlsdCRyb3dbY291bnRzZmlsdCRyb3cgPT0gIkVOU0ZIRVAwMDAwMDAzNDE3NyJdCmdvaQojIHNlcHRpbi0yQiBpc29mb3JtIFgyCiMgRU5TRkhFUDAwMDAwMDE1NzY1CmdvaSA8LSBjb3VudHNmaWx0JHJvd1tjb3VudHNmaWx0JHJvdyA9PSAiRU5TRkhFUDAwMDAwMDE1NzY1Il0KZ29pCiMgQ0xPQ0staW50ZXJhY3RpbmcgcGFjZW1ha2VyLWxpa2UKIyBFTlNGSEVQMDAwMDAwMTczMDMKIyBGdW5oZTJFS20wMjY4NDYKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMTczMDMiXQpnb2kKIyB2YXNvcHJlc3NpbiBWMiByZWNlcHRvci1saWtlCiMgRnVuaGUyRUttMDI2NzIxCiMgRU5TRkhFUDAwMDAwMDAwMDM2CmdvaSA8LSBjb3VudHNmaWx0JHJvd1tjb3VudHNmaWx0JHJvdyA9PSAiRU5TRkhFUDAwMDAwMDAwMDM2Il0KZ29pCiMgc29kaXVtL3BvdGFzc2l1bS10cmFuc3BvcnRpbmcgQVRQYXNlIHN1YnVuaXQgYmV0YS0xLWludGVyYWN0aW5nIHByb3RlaW4gMQojIEVOU0ZIRVAwMDAwMDAzMTEwOAojIEZ1bmhlMkVLbTAwMTE3NApnb2kgPC0gY291bnRzZmlsdCRyb3dbY291bnRzZmlsdCRyb3cgPT0gIkVOU0ZIRVAwMDAwMDAzMTEwOCJdCmdvaQojIHNlcHRpbi0yCiMgRnVuaGUyRUttMDEyMTgyCiMgRU5TRkhFUDAwMDAwMDE2ODUzCmdvaSA8LSBjb3VudHNmaWx0JHJvd1tjb3VudHNmaWx0JHJvdyA9PSAiRU5TRkhFUDAwMDAwMDE2ODUzIl0KZ29pCiMgb3RvcGV0cmluLTIKIyBGdW5oZTJFS20wMzU0MjcKIyBFTlNGSEVQMDAwMDAwMjY0MTEKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMjY0MTEiXQpnb2kKIyBjbGF1ZGluIDgKIyBGdW5oZTJFS20wMzc3MTgKIyBFTlNGSEVQMDAwMDAwMDYyODIKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMDYyODIiXQpnb2kKIyBjbGF1ZGluIDQKIyBFTlNGSEVQMDAwMDAwMDM5MDgKIyBGdW5oZTJFS20wMDcxNDkKZ29pIDwtIGNvdW50c2ZpbHQkcm93W2NvdW50c2ZpbHQkcm93ID09ICJFTlNGSEVQMDAwMDAwMDM5MDgiXQpnb2kKYWxsX2dvaTwtYygiRU5TRkhFUDAwMDAwMDA3MjIwLjEiLCJFTlNGSEVQMDAwMDAwMjU4NDEiLCJFTlNGSEVQMDAwMDAwMTk1MTAiLAogICAgICAgICAgICJFTlNGSEVQMDAwMDAwMTUzODMiLCJFTlNGSEVQMDAwMDAwMDk3NTMiLCJFTlNGSEVQMDAwMDAwMDY3MjUiLCJFTlNGSEVQMDAwMDAwMDgzOTMiLAogICAgICAgICAgICJFTlNGSEVQMDAwMDAwMTMzMjQiLCJFTlNGSEVQMDAwMDAwMDE2MDkiLCJFTlNGSEVQMDAwMDAwMTMzMjQiLCJFTlNGSEVQMDAwMDAwMzQxNzciLAogICAgICAgICAgICJFTlNGSEVQMDAwMDAwMTU3NjUiLCJFTlNGSEVQMDAwMDAwMTczMDMiLCJFTlNGSEVQMDAwMDAwMDAwMzYiLCJFTlNGSEVQMDAwMDAwMzExMDgiLAogICAgICAgICAgICJFTlNGSEVQMDAwMDAwMTY4NTMiLCJFTlNGSEVQMDAwMDAwMDM5MDgiKQpgYGAKCiMgRXhwbG9yYXRvcnkgUGxvdHMKCkxvZyBjb3VudHMgYmVmb3JlIG5vcm1hbGl6YXRpb246CmBgYHtyIHJhdywgcmVzdWx0cz0ic2hvdyIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKSB9CgojIGxvZyBjb3VudHMgYmVmb3JlIERFCmJveHBsb3QobG9nKGNvdW50cy5maWx0KzEpLCBsYXMgPSAyLCBtYWluID0gIiIpCgpgYGAKCkxvZyBjb3VudHMgYWZ0ZXIgY3BtIG5vcm1hbGl6YXRpb24KYGBge3Igbm9ybSwgcmVzdWx0cz0ic2hvdyIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKSB9CiMgLS0tLS0tLS0tLS0tLS0tCgojIERFIGFuYWx5c2lzCgojIC0tLS0tLS0tLS0tLS0tLQoKZ2VuZXMgPSBER0VMaXN0KGNvdW50ID0gY291bnRzLmZpbHQsIGdyb3VwID0gY29uZGl0aW9uX3BoeXNpb2xvZ3lfY2xhZGUpCmdlbmVzID0gY2FsY05vcm1GYWN0b3JzKCBnZW5lcyApCgojIHdyaXRlIG5vcm1hbGl6ZWQgY291bnRzCmRpciA8LSAifi9Eb2N1bWVudHMvVUNEYXZpcy9XaGl0ZWhlYWQvIgp0bXAgPC0gYXMuZGF0YS5mcmFtZShjcG0oZ2VuZXMpKQp0bXAkRW5zZW1ibCA8LSByb3duYW1lcyh0bXApCnRtcCA8LSBkcGx5cjo6c2VsZWN0KHRtcCwgRW5zZW1ibCwgZXZlcnl0aGluZygpKQp3cml0ZS5jc3YodG1wLCBmaWxlID0gZmlsZS5wYXRoKGRpciwgIm5vcm1hbGl6ZWRfY291bnRzLmNzdiIpLCBxdW90ZSA9IEYsIHJvdy5uYW1lcyA9IEYpCgp2b2JqID0gdm9vbSggZ2VuZXMsIGRlc2lnbiwgcGxvdD1UUlVFKQpsY3BtIDwtIGNwbShnZW5lcyRjb3VudHMsIGxvZyA9IFRSVUUpCgojIGxvZyBjb3VudHMgYWZ0ZXIgREUKCmJveHBsb3QobGNwbSwgbGFzID0gMiwgbWFpbiA9ICIiKQpwbG90KGNvbFN1bXModChsY3BtKSkpCmBgYAoKVm9vbSB3ZWlnaHRzOgoKYGBge3Igdm9vbSwgcmVzdWx0cz0ic2hvdyIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKSB9Cgp2d3RzIDwtIHZvb21XaXRoUXVhbGl0eVdlaWdodHMoZ2VuZXMsIGRlc2lnbj1kZXNpZ24sIG5vcm1hbGl6YXRpb249InF1YW50aWxlIiwgcGxvdD1UUlVFKQpgYGAKClRoZSByYW5kb20gZWZmZWN0cyBvZiBgc3BlY2llc2AgYXJlIHRha2VuIGludG8gYWNjb3VudCB3aXRoIHRoZSBgZHVwbGljYXRlQ29ycmVsYXRpb25gIGZ1bmN0aW9uLCB3aGljaCBlc3RpbWF0ZXMgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gc3BlY2llcy4gVGhpcyByZWZsZWN0cyB0aGUgYmV0d2Vlbi1zcGVjaWVzIHZhcmlhYmlsaXR5LiBUaGUgaGlnaGVyIHRoZSBjb3JyZWxhdGlvbiAoMC0xLjApLCB0aGUgaGlnaGVyIHRoZSB2YXJpYWJpbGl0eSBiZXR3ZWVuIHNwZWNpZXMuCgpgYGB7ciByYW5kb21lZmZlY3RzLCByZXN1bHRzPSJzaG93IiwgZmlnLndpZHRoPTExLCBmaWcucGF0aD0nZmlndXJlcy8nLCBkZXY9YygncG5nJywgJ3BkZicpIH0KY29yZml0IDwtIGR1cGxpY2F0ZUNvcnJlbGF0aW9uKHZvYmosZGVzaWduLGJsb2NrPUV4cERlc2lnbiRzcGVjaWVzKQoKY29yZml0JGNvbnNlbnN1cwojWzFdIDAuNzUxMzgxCmBgYAoKIyMjIEluZGl2aWR1YWxzIGNsdXN0ZXJlZCBieSBvdmVyYWxsIGV4cHJlc3Npb24KCmBgYHtyIFBsYWluSGVhdG1hcCwgZmlnLmtlZXA9Imxhc3QiLCBmaWcud2lkdGg9MTEsIGZpZy5wYXRoPSdmaWd1cmVzLycsIGRldj1jKCdwbmcnLCAncGRmJyl9CmNvdW50c19yb3VuZDwtcm91bmQoY291bnRzLmZpbHQsZGlnaXRzPTApCmRkcyA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IGNvdW50c19yb3VuZCxjb2xEYXRhID0gRXhwRGVzaWduLGRlc2lnbiA9IGRlc2lnbikKcmxkIDwtIHZzdChkZHMsIGJsaW5kID0gRkFMU0UsZml0VHlwZT0nbG9jYWwnKQpzYW1wbGVEaXN0cyA8LSBkaXN0KHQoYXNzYXkocmxkKSkpCmRmIDwtIGFzLmRhdGEuZnJhbWUoY29sRGF0YShkZHMpWyxjKCJwaHlzaW9sb2d5IiwiY29uZGl0aW9uIiwiY2xhZGUiKV0pCnNhbXBsZURpc3RNYXRyaXggPC0gYXMubWF0cml4KCBzYW1wbGVEaXN0cyApCmNvbG9ycyA8LSBjb2xvclJhbXBQYWxldHRlKCByZXYoYnJld2VyLnBhbCg5LCAiQmx1ZXMiKSkgKSgyNTUpCnBoZWF0bWFwKHNhbXBsZURpc3RNYXRyaXgsCiAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9IHNhbXBsZURpc3RzLAogICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX2NvbHMgPSBzYW1wbGVEaXN0cywKICAgICAgICAgY29sID0gY29sb3JzLCBhbm5vdGF0aW9uID0gZGYsIHNob3dfcm93bmFtZXM9RikKYGBgCgojIyMgSW5kaXZpZHVhbHMgY2x1c3RlcmVkIGJ5IFRvcCAxMDAgZ2VuZXMKCmBgYHtyIE1pbmlQbGFpbkdlbmVIZWF0bWFwLCBlY2hvPUZBTFNFLCBmaWcua2VlcD0ibGFzdCIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKX0Kc2VsZWN0MTAwIDwtIG9yZGVyKHJvd01lYW5zKGNvdW50cyhkZHMsbm9ybWFsaXplZD1GQUxTRSkpLGRlY3JlYXNpbmc9VFJVRSlbMToxMDBdCnNhbXBsZURpc3RzIDwtIGRpc3QodChhc3NheShybGQpW3NlbGVjdDEwMCxdKSkKcGhlYXRtYXAoYXNzYXkocmxkKVtzZWxlY3QxMDAsXSwgc2hvd19yb3duYW1lcz1UUlVFLGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9IHNhbXBsZURpc3RzLAogICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX2NvbHMgPSBzYW1wbGVEaXN0cywgYW5ub3RhdGlvbl9jb2w9ZGYpCmBgYAoKIyMjIEluZGl2aWR1YWxzIGNsdXN0ZXJlZCBieSB0b3AgNTAgZ2VuZSBleHByZXNzaW9uCgoKYGBge3IgTWluaVBsYWluSGVhdG1hcCwgZWNobz1GQUxTRSwgZmlnLmtlZXA9Imxhc3QiLCBmaWcud2lkdGg9MTEsIGZpZy5wYXRoPSdmaWd1cmVzLycsIGRldj1jKCdwbmcnLCAncGRmJyl9CgpzZWxlY3Q1MCA8LSBvcmRlcihyb3dNZWFucyhjb3VudHMoZGRzLG5vcm1hbGl6ZWQ9RkFMU0UpKSxkZWNyZWFzaW5nPVRSVUUpWzE6NTBdCgpzYW1wbGVEaXN0cyA8LSBkaXN0KHQoYXNzYXkocmxkKVtzZWxlY3Q1MCxdKSkKc2FtcGxlRGlzdE1hdHJpeCA8LSBhcy5tYXRyaXgoIHNhbXBsZURpc3RzICkKCnBoZWF0bWFwKHNhbXBsZURpc3RNYXRyaXgsIHNob3dfcm93bmFtZXM9VCxjbHVzdGVyaW5nX2Rpc3RhbmNlX3Jvd3MgPSBzYW1wbGVEaXN0cywKICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9jb2xzID0gc2FtcGxlRGlzdHMsIGFubm90YXRpb25fY29sPWRmKQpgYGAKCiMjIyBQQ0EgZm9yIG92ZXJhbGwgZXhwcmVzc2lvbgoKYGBge3IgcGxhaW5QQ0EsIGZpZy5rZWVwPSJsYXN0IiwgZmlnLndpZHRoPTExLCBmaWcucGF0aD0nZmlndXJlcy8nLCBkZXY9YygncG5nJywgJ3BkZicpfQoKY293cGxvdDo6cGxvdF9ncmlkKCBwbG90UENBKHJsZCwgaW50Z3JvdXA9ImNvbmRpdGlvbiIpLAogICAgICAgICAgICAgICAgICAgIHBsb3RQQ0EocmxkLCBpbnRncm91cD0icGh5c2lvbG9neSIpLAogICAgICAgICAgICAgICAgICAgIHBsb3RQQ0EocmxkLCBpbnRncm91cD0iY2xhZGUiKSwKICAgICAgICAgICAgICAgICAgICBwbG90UENBKHJsZCwgaW50Z3JvdXA9YygiY2xhZGUiLCJwaHlzaW9sb2d5IiwiY29uZGl0aW9uIikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBhbGlnbj0iYyIsIG5jb2w9MikKYGBgCgoKIyBDb250cmFzdHMKCkFmdGVyIHJ1bm5pbmcgdGhlIGBsbUZpdGAgZnVuY3Rpb24sIHdoaWNoIGZpdHMgdGhlIGxpbmVhciBtb2RlbCBmb3IgZWFjaCBnZW5lIGluIHRoZSBtYXRyaXggYW5kIHRha2VzIHRoZSByYW5kb20gZWZmZWN0cyBjb3JyZWxhdGlvbiBpbnRvIGFjY291bnQsIHRoZSByZXN1bHRpbmcgbGluZWFyIG1vZGVsIGZpdCBpcyB0aGVuIHVzZWQgdG8gY29tcHV0ZSB0aGUgZXN0aW1hdGVkIGNvZWZmaWNpZW50cyBhbmQgc3RhbmRhcmQgZXJyb3JzIGZvciBhIGdpdmVuIHNldCBvZiBjb250cmFzdHM6CgpgYGB7ciBsbWZpdCwgcmVzdWx0cz0ic2hvdyIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKSB9CmZpdFJhbiA8LSBsbUZpdCh2b2JqLGRlc2lnbixibG9jaz1FeHBEZXNpZ24kc3BlY2llcyxjb3JyZWxhdGlvbj1jb3JmaXQkY29uc2Vuc3VzKQojY29sbmFtZXMoY29lZihmaXRSYW4pKQp5IDwtIHJub3JtKG4gPSBucm93KGRlc2lnbikpCmR1bW15Lm1vZCA8LSBsbSh5IH4gcGh5c2lvbG9neSpjb25kaXRpb24qY2xhZGUsIAogICAgICAgICAgICAgICAgZGF0YSA9IEV4cERlc2lnbikKcGFpcnMgPC0gcGFpcnMoZW1tZWFucyhkdW1teS5tb2QsIH5jb25kaXRpb258Y2xhZGUqcGh5c2lvbG9neSApLCByZXZlcnNlID0gVCkKY29udHJhc3QubWF0cml4IDwtIHBhaXJzQGxpbmZjdAp0bXAgPC0gcGFpcnNAZ3JpZApjb250cmFzdHMgPC0gZ3N1YigiICIsICIiLCB0bXAkY29udHJhc3QpCmNvbnRyYXN0cyA8LSBnc3ViKCItIiwgIl92XyIsIGNvbnRyYXN0cykKY29udHJhc3RzIDwtIHBhc3RlMChjb250cmFzdHMsICJfIiwgdG1wJGNsYWRlLCAiXyIsIHRtcCRwaHlzaW9sb2d5KQpyb3duYW1lcyhjb250cmFzdC5tYXRyaXgpIDwtIGNvbnRyYXN0cwoKY29udHJhc3RzCmBgYAoKCmBgYHtyIGNvbnRyYXN0czEsIHJlc3VsdHM9InNob3cifQp0YWJsZXMgPC0gbGFwcGx5KGNvbnRyYXN0cywgZnVuY3Rpb24oY29udHIpewogICAgcHJpbnQoY29udHIpCiAgICBjbSA8LSBjb250cmFzdC5tYXRyaXhbY29udHIsXQogICAgcGggPC0gc2FwcGx5KHN0cnNwbGl0KGFzLmNoYXJhY3Rlcihjb250ciksICJfIiksIHRhaWwsIDEpCiAgICBjbCA8LSBzYXBwbHkoc3Ryc3BsaXQoYXMuY2hhcmFjdGVyKGNvbnRyKSwgIl8iKSwgdGFpbCwgMikKICAgIHRtcCA8LSBjb250cmFzdHMuZml0KGZpdFJhbiwgY29udHJhc3RzID0gY20pCiAgICB0bXAgPC0gZUJheWVzKHRtcCkKICAgIHRtcDIgPC0gdG9wVGFibGUodG1wLCBuID0gSW5mLCBzb3J0LmJ5ID0gIlAiKQogICAgI3RtcDMgPC0gdG1wMgogICAgI3RtcDMkcm93IDwtIHJvd25hbWVzKHRtcDMpCiAgICAjdG1wMyA8LSBtZXJnZShhbm4sdG1wMyxieS54ID0gImVuc2VtYmxfcGVwdGlkZV9pZCIsIGJ5LnkgPSAicm93IiwgYWxsID0gVFJVRSkKICAgICN0bXAzIDwtIHRtcDNbb3JkZXIodG1wMyRhZGouUC5WYWwpLF0KICAgIGZpbGVuYW1lIDwtIHBhc3RlMChjb250ciwgIi5jc3YiKQogICAgI3dyaXRlLmNzdih0bXAyLCBmaWxlID0gZmlsZS5wYXRoKGRpciwgZmlsZW5hbWUpLHF1b3RlID0gRikKICAgIHRhYiA8LSBrYWJsZShoZWFkKHRtcDIsIDIwKSwgZGlnaXRzID0gNSwgcm93Lm5hbWVzID0gRikKICAgIGhlYWRlcjEgPC0gNgogICAgbmFtZXMoaGVhZGVyMSkgPC0gcGFzdGUwKCJUb3AgMjAgZ2VuZXMgZm9yICIsIGNvbnRyKQogICAgaGVhZGVyMiA8LSA2CiAgICBuYW1lcyhoZWFkZXIyKSA8LSBwYXN0ZTAoIk51bWJlciBvZiBnZW5lcyB3aXRoIGFkanVzdGVkIFAgPCAwLjA1ID0gIiwgbGVuZ3RoKHdoaWNoKHRtcDIkYWRqLlAuVmFsIDwgMC4wNSkpKQogICAgaGVhZGVyMyA8LSA2CiAgICBuYW1lcyhoZWFkZXIzKSA8LSBwYXN0ZTAoIk91dHB1dCBmaWxlIGlzICIsIGZpbGVuYW1lKQogICAgdGFiIDwtIHRhYiAlPiUgYWRkX2hlYWRlcl9hYm92ZShoZWFkZXIzLCBhbGlnbiA9ICdsJykgJT4lIGFkZF9oZWFkZXJfYWJvdmUoaGVhZGVyMiwgYWxpZ24gPSAnbCcpICU+JSBhZGRfaGVhZGVyX2Fib3ZlKGhlYWRlcjEsIGFsaWduID0gJ2wnLCBmb250X3NpemUgPSAibGFyZ2VyIiwgYm9sZCA9IFQpCiAgICB0YWIgPC0gdGFiICU+JSBrYWJsZV9zdHlsaW5nKCkKICAgIHJldHVybihsaXN0KHRhYiwgbnVtcCA9IGxlbmd0aCh3aGljaCh0bXAyJGFkai5QLlZhbCA8IDAuMDUpKSkpCn0KKQoKYGBgCgojIFRocmVlLXdheSBjb250cmFzdHMKClRoZSBudW1iZXIgb2YgZ2VuZXMgc2lnbmlmaWNhbnQgZm9yIHRoZSB0aHJlZS13YXkgaW50ZXJhY3Rpb24gb2YgYGNvbmRpdGlvbjpwaHlzaW9sb2d5OmNsYWRlYDogCgpgYGB7ciB0aHJlZXdheSwgcmVzdWx0cz0ic2hvdyJ9CnNpZ3BzIDwtIHVubGlzdChsYXBwbHkodGFibGVzLCBmdW5jdGlvbih4KXhbWzJdXSkpCnN1bXRhYiA8LSBkYXRhLmZyYW1lKENvbXBhcmlzb24gPSBjb250cmFzdHMsIGBOdW1iZXIgb2YgZ2VuZXMgd2l0aCBhZGp1c3RlZCBQIDwgMC4wNWAgPSBzaWdwcywKICAgICAgICAgICAgICAgICAgICAgY2hlY2submFtZXMgPSBGKQprYWJsZShzdW10YWIsIGFsaWduID0gJ2MnKSAlPiUga2FibGVfc3R5bGluZygpICU+JQogIGFkZF9oZWFkZXJfYWJvdmUoYygiT3ZlcnZpZXcgb2YgcmVzdWx0cyIgPSAyKSwgZm9udF9zaXplID0gImxhcmdlciIsIGJvbGQgPSBULCBhbGlnbiA9ICJsIikKYGBgCgojIFR3by13YXkgY29udHJhc3RzCgpUaGVzZSBnZW5lcyBkZW1vbnN0cmF0ZSBhIGNvbnNlcnZlZCByZXNwb25zZSB0byBleHBlcmltZW50YWwgY29uZGl0aW9uIGFjcm9zcyBNIG9yIEZXIHBoeXNpb2xvZ2llcywgcmVnYXJkbGVzcyBvZiBjbGFkZS4gCgpgYGB7ciB0d293YXksIHJlc3VsdHM9InNob3cifQp5IDwtIHJub3JtKG4gPSBucm93KGRlc2lnbikpCmR1bW15Lm1vZCA8LSBsbSh5IH4gcGh5c2lvbG9neSpjb25kaXRpb24qY2xhZGUsIAogICAgICAgICAgICAgICAgZGF0YSA9IEV4cERlc2lnbikKcGFpcnMgPC0gcGFpcnMoZW1tZWFucyhkdW1teS5tb2QsIH5jb25kaXRpb258cGh5c2lvbG9neSApLCByZXZlcnNlID0gVCkKY29udHJhc3QubWF0cml4IDwtIHBhaXJzQGxpbmZjdAp0bXAgPC0gcGFpcnNAZ3JpZApjb250cmFzdHMgPC0gZ3N1YigiICIsICIiLCB0bXAkY29udHJhc3QpCmNvbnRyYXN0cyA8LSBnc3ViKCItIiwgIl92XyIsIGNvbnRyYXN0cykKY29udHJhc3RzIDwtIHBhc3RlMChjb250cmFzdHMsICJfIiwgdG1wJHBoeXNpb2xvZ3kpCnJvd25hbWVzKGNvbnRyYXN0Lm1hdHJpeCkgPC0gY29udHJhc3RzCgpjb250cmFzdHMKCnRhYmxlcyA8LSBsYXBwbHkoY29udHJhc3RzLCBmdW5jdGlvbihjb250cil7CiAgcHJpbnQoY29udHIpCiAgY20gPC0gY29udHJhc3QubWF0cml4W2NvbnRyLF0KICBwaCA8LSBzYXBwbHkoc3Ryc3BsaXQoYXMuY2hhcmFjdGVyKGNvbnRyKSwgIl8iKSwgdGFpbCwgMSkKICBjbCA8LSBzYXBwbHkoc3Ryc3BsaXQoYXMuY2hhcmFjdGVyKGNvbnRyKSwgIl8iKSwgdGFpbCwgMikKICB0bXAgPC0gY29udHJhc3RzLmZpdChmaXRSYW4sIGNvbnRyYXN0cyA9IGNtKQogIHRtcCA8LSBlQmF5ZXModG1wKQogIHRtcDIgPC0gdG9wVGFibGUodG1wLCBuID0gSW5mLCBzb3J0LmJ5ID0gIlAiKQogICN0bXAzIDwtIHRtcDIKICAjdG1wMyRyb3cgPC0gcm93bmFtZXModG1wMykKICAjdG1wMyA8LSBtZXJnZShhbm4sdG1wMyxieS54ID0gImVuc2VtYmxfcGVwdGlkZV9pZCIsIGJ5LnkgPSAicm93IiwgYWxsID0gVFJVRSkKICAjdG1wMyA8LSB0bXAzW29yZGVyKHRtcDMkYWRqLlAuVmFsKSxdCiAgZmlsZW5hbWUgPC0gcGFzdGUwKGNvbnRyLCAiLmNzdiIpCiAgI3dyaXRlLmNzdih0bXAyLCBmaWxlID0gZmlsZS5wYXRoKGRpciwgZmlsZW5hbWUpLHF1b3RlID0gRikKICB0YWIgPC0ga2FibGUoaGVhZCh0bXAyLCAyMCksIGRpZ2l0cyA9IDUsIHJvdy5uYW1lcyA9IEYpCiAgaGVhZGVyMSA8LSA2CiAgbmFtZXMoaGVhZGVyMSkgPC0gcGFzdGUwKCJUb3AgMjAgZ2VuZXMgZm9yICIsIGNvbnRyKQogIGhlYWRlcjIgPC0gNgogIG5hbWVzKGhlYWRlcjIpIDwtIHBhc3RlMCgiTnVtYmVyIG9mIGdlbmVzIHdpdGggYWRqdXN0ZWQgUCA8IDAuMDUgPSAiLCBsZW5ndGgod2hpY2godG1wMiRhZGouUC5WYWwgPCAwLjA1KSkpCiAgaGVhZGVyMyA8LSA2CiAgbmFtZXMoaGVhZGVyMykgPC0gcGFzdGUwKCJPdXRwdXQgZmlsZSBpcyAiLCBmaWxlbmFtZSkKICB0YWIgPC0gdGFiICU+JSBhZGRfaGVhZGVyX2Fib3ZlKGhlYWRlcjMsIGFsaWduID0gJ2wnKSAlPiUgYWRkX2hlYWRlcl9hYm92ZShoZWFkZXIyLCBhbGlnbiA9ICdsJykgJT4lIGFkZF9oZWFkZXJfYWJvdmUoaGVhZGVyMSwgYWxpZ24gPSAnbCcsIGZvbnRfc2l6ZSA9ICJsYXJnZXIiLCBib2xkID0gVCkKICB0YWIgPC0gdGFiICU+JSBrYWJsZV9zdHlsaW5nKCkKICByZXR1cm4obGlzdCh0YWIsIG51bXAgPSBsZW5ndGgod2hpY2godG1wMiRhZGouUC5WYWwgPCAwLjA1KSkpKQp9CgopCmBgYAoKIyBIZWF0bWFwcwoKYGBge3IgcmVhZHR3by13YXksIHJlc3VsdHM9J2hpZGUnLCBpbmNsdWRlPUZBTFNFfQpNIDwtIHJlYWQuY3N2KCJ+L0RvY3VtZW50cy9VQ0RhdmlzL1doaXRlaGVhZC8xNV9wcHRfdl8wLjJfcHB0X00uY3N2IixzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGhlYWRlciA9IFRSVUUsIHJvdy5uYW1lcyA9IE5VTEwpCkZXIDwtIHJlYWQuY3N2KCJ+L0RvY3VtZW50cy9VQ0RhdmlzL1doaXRlaGVhZC8xNV9wcHRfdl8wLjJfcHB0X0ZXLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwgaGVhZGVyID0gVFJVRSwgcm93Lm5hbWVzID0gTlVMTCkKQ2xhZGUzX00gPC0gcmVhZC5jc3YoIn4vRG9jdW1lbnRzL1VDRGF2aXMvV2hpdGVoZWFkLzE1X3BwdF92XzAuMl9wcHRfQ2xhZGUzX00uY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLCBoZWFkZXIgPSBUUlVFLCByb3cubmFtZXMgPSBOVUxMKQpDbGFkZTNfRlcgPC0gcmVhZC5jc3YoIn4vRG9jdW1lbnRzL1VDRGF2aXMvV2hpdGVoZWFkLzE1X3BwdF92XzAuMl9wcHRfQ2xhZGUzX0ZXLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwgaGVhZGVyID0gVFJVRSwgcm93Lm5hbWVzID0gTlVMTCkKQ2xhZGUyX00gPC0gcmVhZC5jc3YoIn4vRG9jdW1lbnRzL1VDRGF2aXMvV2hpdGVoZWFkLzE1X3BwdF92XzAuMl9wcHRfQ2xhZGUyX00uY3N2IixzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGhlYWRlciA9IFRSVUUsIHJvdy5uYW1lcyA9IE5VTEwpCkNsYWRlMl9GVyA8LSByZWFkLmNzdigifi9Eb2N1bWVudHMvVUNEYXZpcy9XaGl0ZWhlYWQvMTVfcHB0X3ZfMC4yX3BwdF9DbGFkZTJfRlcuY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLCBoZWFkZXIgPSBUUlVFLCByb3cubmFtZXMgPSBOVUxMKQpDbGFkZTFfTSA8LSByZWFkLmNzdigifi9Eb2N1bWVudHMvVUNEYXZpcy9XaGl0ZWhlYWQvMTVfcHB0X3ZfMC4yX3BwdF9DbGFkZTFfTS5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGhlYWRlciA9IFRSVUUsIHJvdy5uYW1lcyA9IE5VTEwpCkNsYWRlMV9GVyA8LSByZWFkLmNzdigifi9Eb2N1bWVudHMvVUNEYXZpcy9XaGl0ZWhlYWQvMTVfcHB0X3ZfMC4yX3BwdF9DbGFkZTFfRlcuY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLCBoZWFkZXIgPSBUUlVFLCByb3cubmFtZXMgPSBOVUxMKQojIHNpZyBnZW5lcyBNIGFuZCBGVwojIHR3by13YXkKIyBjb25zZXJ2ZWQgcmVzcG9uc2UKI2RpbShNKQpNX3NpZyA8LSBNW00kYWRqLlAuVmFsIDw9IDAuMDUsXSAKTV9zaWcgPC0gTV9zaWdbIWlzLm5hKE1fc2lnJGFkai5QLlZhbCksXQpNX3NpZyA8LSBNX3NpZyRYCiNsZW5ndGgoTV9zaWcpCiNkaW0oRlcpCkZXX3NpZyA8LSBGV1tGVyRhZGouUC5WYWwgPD0gMC4wNSxdIApGV19zaWcgPC0gRldfc2lnWyFpcy5uYShGV19zaWckYWRqLlAuVmFsKSxdCkZXX3NpZyA8LSBGV19zaWckWAojbGVuZ3RoKEZXX3NpZykKYGBgCgpgYGB7ciByZWFkdGhyZWV3YXksIHJlc3VsdHM9J2hpZGUnLCBpbmNsdWRlPUZBTFNFfQojIENsYWRlIDMgLSBzcGVjaWZpYyByZXNwb25zZQojIHNpZyBnZW5lcyBDbGFkZSAzLCBNCiMgYnV0IG5vdCBzaWcgZm9yIDItd2F5CgpDbGFkZTNfTV9zaWcgPC0gQ2xhZGUzX01bQ2xhZGUzX00kYWRqLlAuVmFsIDw9IDAuMDUsXQpDbGFkZTNfTV9zaWcgPC0gQ2xhZGUzX01fc2lnWyFpcy5uYShDbGFkZTNfTV9zaWckYWRqLlAuVmFsKSxdCmRpbShDbGFkZTNfTV9zaWcpCkNsYWRlM19NX3NpZ19zcGVjaWZpYyA8LSBDbGFkZTNfTV9zaWdbIUNsYWRlM19NX3NpZyRYICVpbiUgTV9zaWcsXQpkaW0oQ2xhZGUzX01fc2lnX3NwZWNpZmljKQpDbGFkZTNfTV9zaWdfc3BlY2lmaWMgPC0gQ2xhZGUzX01fc2lnX3NwZWNpZmljJFgKCiMgQ2xhZGUgMyAtIHNwZWNpZmljIHJlc3BvbnNlCiMgc2lnIGdlbmVzIENsYWRlIDEsRlcKIyBidXQgbm90IHNpZyBmb3IgMi13YXkKCkNsYWRlM19GV19zaWcgPC0gQ2xhZGUzX0ZXW0NsYWRlM19GVyRhZGouUC5WYWwgPD0gMC4wNSxdCkNsYWRlM19GV19zaWcgPC0gQ2xhZGUzX0ZXX3NpZ1shaXMubmEoQ2xhZGUzX0ZXX3NpZyRhZGouUC5WYWwpLF0KZGltKENsYWRlM19GV19zaWcpCkNsYWRlM19GV19zaWdfc3BlY2lmaWMgPC0gQ2xhZGUzX0ZXX3NpZ1shQ2xhZGUzX0ZXX3NpZyRYICVpbiUgRldfc2lnLF0KZGltKENsYWRlM19GV19zaWdfc3BlY2lmaWMpCkNsYWRlM19GV19zaWdfc3BlY2lmaWMgPC0gQ2xhZGUzX0ZXX3NpZ19zcGVjaWZpYyRYCgojIENsYWRlIDIgLSBzcGVjaWZpYyByZXNwb25zZQojIHNpZyBnZW5lcyBDbGFkZSAyLCBNCiMgYnV0IG5vdCBzaWcgZm9yIDItd2F5CgpDbGFkZTJfTV9zaWcgPC0gQ2xhZGUyX01bQ2xhZGUyX00kYWRqLlAuVmFsIDw9IDAuMDUsXQpDbGFkZTJfTV9zaWcgPC0gQ2xhZGUyX01fc2lnWyFpcy5uYShDbGFkZTJfTV9zaWckYWRqLlAuVmFsKSxdCmRpbShDbGFkZTJfTV9zaWcpCkNsYWRlMl9NX3NpZ19zcGVjaWZpYyA8LSBDbGFkZTJfTV9zaWdbIUNsYWRlMl9NX3NpZyRYICVpbiUgTV9zaWcsXQpkaW0oQ2xhZGUyX01fc2lnX3NwZWNpZmljKQpDbGFkZTJfTV9zaWdfc3BlY2lmaWMgPC0gQ2xhZGUyX01fc2lnX3NwZWNpZmljJFgKCiMgQ2xhZGUgMiAtIHNwZWNpZmljIHJlc3BvbnNlCiMgc2lnIGdlbmVzIENsYWRlIDIsIEZXCiMgYnV0IG5vdCBzaWcgZm9yIDItd2F5CgpDbGFkZTJfRldfc2lnIDwtIENsYWRlMl9GV1tDbGFkZTJfRlckYWRqLlAuVmFsIDw9IDAuMDUsXQpDbGFkZTJfRldfc2lnIDwtIENsYWRlMl9GV19zaWdbIWlzLm5hKENsYWRlMl9GV19zaWckYWRqLlAuVmFsKSxdCmRpbShDbGFkZTJfRldfc2lnKQpDbGFkZTJfRldfc2lnX3NwZWNpZmljIDwtIENsYWRlMl9GV19zaWdbIUNsYWRlMl9GV19zaWckWCAlaW4lIEZXX3NpZyxdCmRpbShDbGFkZTJfRldfc2lnX3NwZWNpZmljKQpDbGFkZTJfRldfc2lnX3NwZWNpZmljIDwtIENsYWRlMl9GV19zaWdfc3BlY2lmaWMkWAoKIyBDbGFkZSAxIC0gc3BlY2lmaWMgcmVzcG9uc2UKIyBzaWcgZ2VuZXMgQ2xhZGUgMSwgTQojIGJ1dCBub3Qgc2lnIGZvciAyLXdheQoKQ2xhZGUxX01fc2lnIDwtIENsYWRlMV9NW0NsYWRlMV9NJGFkai5QLlZhbCA8PSAwLjA1LF0KQ2xhZGUxX01fc2lnIDwtIENsYWRlMV9NX3NpZ1shaXMubmEoQ2xhZGUxX01fc2lnJGFkai5QLlZhbCksXQpkaW0oQ2xhZGUxX01fc2lnKQpDbGFkZTFfTV9zaWdfc3BlY2lmaWMgPC0gQ2xhZGUxX01fc2lnWyFDbGFkZTFfTV9zaWckWCAlaW4lIE1fc2lnLF0KZGltKENsYWRlMV9NX3NpZ19zcGVjaWZpYykKQ2xhZGUxX01fc2lnX3NwZWNpZmljIDwtIENsYWRlMV9NX3NpZ19zcGVjaWZpYyRYCgojIENsYWRlIDEgLSBzcGVjaWZpYyByZXNwb25zZQojIHNpZyBnZW5lcyBDbGFkZSAxLCBGVwojIGJ1dCBub3Qgc2lnIGZvciAyLXdheQoKQ2xhZGUxX0ZXX3NpZyA8LSBDbGFkZTFfRldbQ2xhZGUxX0ZXJGFkai5QLlZhbCA8PSAwLjA1LF0KQ2xhZGUxX0ZXX3NpZyA8LSBDbGFkZTFfRldfc2lnWyFpcy5uYShDbGFkZTFfRldfc2lnJGFkai5QLlZhbCksXQpkaW0oQ2xhZGUxX0ZXX3NpZykKQ2xhZGUxX0ZXX3NpZ19zcGVjaWZpYyA8LSBDbGFkZTFfRldfc2lnWyFDbGFkZTFfRldfc2lnJFggJWluJSBGV19zaWcsXQpkaW0oQ2xhZGUxX0ZXX3NpZ19zcGVjaWZpYykKQ2xhZGUxX0ZXX3NpZ19zcGVjaWZpYyA8LSBDbGFkZTFfRldfc2lnX3NwZWNpZmljJFgKYGBgCgpgYGB7ciByZWFkbm9ybWNvdW50cywgcmVzdWx0cz0naGlkZScsIGluY2x1ZGU9RkFMU0V9Cm5vcm1fY291bnRzIDwtIHJlYWQuY3N2KCJ+L0RvY3VtZW50cy9VQ0RhdmlzL1doaXRlaGVhZC9ub3JtYWxpemVkX2NvdW50cy5jc3YiLHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwgaGVhZGVyID0gVFJVRSwgcm93Lm5hbWVzID0gTlVMTCkKI2NvbG5hbWVzKG5vcm1fY291bnRzKQpjb2xzLm5vcm1fY291bnRzIDwtIGNvbG5hbWVzKG5vcm1fY291bnRzKQpzcGVjaWVzX2NvbmRpdGlvbjwtYXMudmVjdG9yKHBhc3RlKHNwZWNpZXMsY29uZGl0aW9uLHNlcD0iLiIpKQpyb3duYW1lcyhub3JtX2NvdW50cykgPC0gbm9ybV9jb3VudHMkRW5zZW1ibApub3JtX2NvdW50cyA8LSBub3JtX2NvdW50c1ssLTFdCmNvbG5hbWVzKG5vcm1fY291bnRzKSA8LSBzcGVjaWVzX2NvbmRpdGlvbgojZGltKG5vcm1fY291bnRzKSAKYGBgCgpgYGB7ciBtZWFucywgcmVzdWx0cz0naGlkZScsIGluY2x1ZGU9RkFMU0V9Cm1lYW5fbm9ybV9jb3VudHM8LXNhcHBseSh1bmlxdWUoY29sbmFtZXMobm9ybV9jb3VudHMpKSwgZnVuY3Rpb24oaSkKICByb3dNZWFucyhub3JtX2NvdW50c1ssY29sbmFtZXMobm9ybV9jb3VudHMpID09IGldKSkKcGggPC0gYygiTSIsIk0iLCJNIiwiTSIsIk0iLCJNIiwiTSIsIk0iLCJNIiwiTSIsIkZXIiwiRlciLCJGVyIsIkZXIiwiTSIsIk0iLCJNIiwiTSIsIkZXIiwiRlciLCJNIiwiTSIsIk0iLCJNIiwiRlciLCJGVyIsIkZXIiwiRlciKQpjbCA8LSBjKCJDbGFkZTEiLCJDbGFkZTEiLCJDbGFkZTEiLCJDbGFkZTEiLCJDbGFkZTEiLCJDbGFkZTEiLCJDbGFkZTEiLCJDbGFkZTEiLCJDbGFkZTEiLCJDbGFkZTEiLCJDbGFkZTEiLCJDbGFkZTEiLCJDbGFkZTEiLCJDbGFkZTEiLCJDbGFkZTIiLCJDbGFkZTIiLCJDbGFkZTIiLCJDbGFkZTIiLCJDbGFkZTIiLCJDbGFkZTIiLCJDbGFkZTMiLCJDbGFkZTMiLCJDbGFkZTMiLCJDbGFkZTMiLCJDbGFkZTMiLCJDbGFkZTMiLCJDbGFkZTMiLCJDbGFkZTMiKQpjb25kaXRpb24gPC0gYygiMTVfcHB0IiwiMC4yX3BwdCIsIjE1X3BwdCIsIjAuMl9wcHQiLCIxNV9wcHQiLCIwLjJfcHB0IiwiMTVfcHB0IiwiMC4yX3BwdCIsIjE1X3BwdCIsIjAuMl9wcHQiLCIxNV9wcHQiLCIwLjJfcHB0IiwiMTVfcHB0IiwiMC4yX3BwdCIsIjE1X3BwdCIsIjAuMl9wcHQiLCIxNV9wcHQiLCIwLjJfcHB0IiwiMTVfcHB0IiwiMC4yX3BwdCIsIjE1X3BwdCIsIjAuMl9wcHQiLCIxNV9wcHQiLCIwLjJfcHB0IiwiMTVfcHB0IiwiMC4yX3BwdCIsIjE1X3BwdCIsIjAuMl9wcHQiKQogIApjb2xuYW1lcyhtZWFuX25vcm1fY291bnRzKQpzYW1wbGVfb3JkZXIgPC0gYygiRl9ncmFuZGlzLjE1X3BwdCIsIkZfZ3JhbmRpcy4wLjJfcHB0IiwiRl9zaW1pbGlzLjE1X3BwdCIsIkZfc2ltaWxpcy4wLjJfcHB0IiwKICAgICAgICAgICAiRl9kaWFwaGFudXMuMTVfcHB0IiwiRl9kaWFwaGFudXMuMC4yX3BwdCIsIkZfaGV0ZXJvY2xpdHVzTURQTC4xNV9wcHQiLCJGX2hldGVyb2NsaXR1c01EUEwuMC4yX3BwdCIsCiAgICAgICAgICAgIkZfaGV0ZXJvY2xpdHVzTURQUC4xNV9wcHQiLCJGX2hldGVyb2NsaXR1c01EUFAuMC4yX3BwdCIsIkZfY2F0YW5hdHVzLjE1X3BwdCIsIkZfY2F0YW5hdHVzLjAuMl9wcHQiLAogICAgICAgICAgICJGX3JhdGhidW5pLjE1X3BwdCIsIkZfcmF0aGJ1bmkuMC4yX3BwdCIsIkZfcGFydmFwaW5pcy4xNV9wcHQiLCJGX3BhcnZhcGluaXMuMC4yX3BwdCIsCiAgICAgICAgICAgIkxfcGFydmEuMTVfcHB0IiwiTF9wYXJ2YS4wLjJfcHB0IiwiTF9nb29kZWkuMTVfcHB0IiwiTF9nb29kZWkuMC4yX3BwdCIsCiAgICAgICAgICAgIkZfY2hyeXNvdHVzLjE1X3BwdCIsIkZfY2hyeXNvdHVzLjAuMl9wcHQiLCJBX3hlbmljYS4xNV9wcHQiLCJBX3hlbmljYS4wLjJfcHB0IiwKICAgICAgICAgICAiRl9ub3RhdHVzLjE1X3BwdCIsIkZfbm90YXR1cy4wLjJfcHB0IiwiRl9vbGl2YWNlb3VzLjE1X3BwdCIsIkZfb2xpdmFjZW91cy4wLjJfcHB0IikKCm1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZCA8LSBtZWFuX25vcm1fY291bnRzWyxzYW1wbGVfb3JkZXJdCgpgYGAKCgpgYGB7ciBtZWFudHdvd2F5LCByZXN1bHRzPSdoaWRlJywgaW5jbHVkZT1GQUxTRX0KbWVhbl9ub3JtX2NvdW50c19vcmRlcmVkX01fc2lnIDwtIG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZFtyb3duYW1lcyhtZWFuX25vcm1fY291bnRzX29yZGVyZWQpICVpbiUgQ2xhZGUxX01fc2lnX3NwZWNpZmljLF0KbWVhbl9ub3JtX2NvdW50c19vcmRlcmVkX0ZXX3NpZyA8LSBtZWFuX25vcm1fY291bnRzX29yZGVyZWRbcm93bmFtZXMobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkKSAlaW4lIEZXX3NpZyxdCm1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9NX0NsYWRlMV9zaWcgPC0gbWVhbl9ub3JtX2NvdW50c19vcmRlcmVkW3Jvd25hbWVzKG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZCkgJWluJSBDbGFkZTFfTV9zaWdfc3BlY2lmaWMsXQptZWFuX25vcm1fY291bnRzX29yZGVyZWRfRldfQ2xhZGUxX3NpZyA8LSBtZWFuX25vcm1fY291bnRzX29yZGVyZWRbcm93bmFtZXMobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkKSAlaW4lIENsYWRlMV9GV19zaWdfc3BlY2lmaWMgLF0KbWVhbl9ub3JtX2NvdW50c19vcmRlcmVkX01fQ2xhZGUyX3NpZyA8LSBtZWFuX25vcm1fY291bnRzX29yZGVyZWRbcm93bmFtZXMobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkKSAlaW4lIENsYWRlMl9NX3NpZ19zcGVjaWZpYyAsXQptZWFuX25vcm1fY291bnRzX29yZGVyZWRfRldfQ2xhZGUyX3NpZyA8LSBtZWFuX25vcm1fY291bnRzX29yZGVyZWRbcm93bmFtZXMobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkKSAlaW4lIENsYWRlMl9GV19zaWdfc3BlY2lmaWMgLF0KbWVhbl9ub3JtX2NvdW50c19vcmRlcmVkX01fQ2xhZGUzX3NpZyA8LSBtZWFuX25vcm1fY291bnRzX29yZGVyZWRbcm93bmFtZXMobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkKSAlaW4lIENsYWRlM19NX3NpZ19zcGVjaWZpYyxdCm1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9GV19DbGFkZTNfc2lnIDwtIG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZFtyb3duYW1lcyhtZWFuX25vcm1fY291bnRzX29yZGVyZWQpICVpbiUgQ2xhZGUzX0ZXX3NpZ19zcGVjaWZpYyAsXQpgYGAKCiMjIE1hcmluZS1DbGFkZSAxICh0aHJlZS13YXkpIHJlc3BvbnNlCgpgYGB7ciBNQ2xhZGUxLCBmaWcua2VlcD0ibGFzdCIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKX0KcmxkIDwtIGxvZzIobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkX01fQ2xhZGUxX3NpZysxKQpnZW5lRGlzdHMgPC0gZGlzdChtZWFuX25vcm1fY291bnRzX29yZGVyZWRfTV9DbGFkZTFfc2lnKQpkZiA8LSBkYXRhLmZyYW1lKHBoLGNsLCBjb25kaXRpb24sc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKcm93bmFtZXMoZGYpIDwtIGNvbG5hbWVzKHJsZCkKcGhlYXRtYXAocmxkLCBzaG93X3Jvd25hbWVzPUZBTFNFLAogICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX3Jvd3MgPSBnZW5lRGlzdHMsIGNsdXN0ZXJfY29scz0gRkFMU0UsYW5ub3RhdGlvbl9jb2w9ZGYpCmBgYAoKIyMgRnJlc2h3YXRlci1DbGFkZSAxICh0aHJlZS13YXkpIHJlc3BvbnNlCgpgYGB7ciBGV0NsYWRlMSwgZmlnLmtlZXA9Imxhc3QiLCBmaWcud2lkdGg9MTEsIGZpZy5wYXRoPSdmaWd1cmVzLycsIGRldj1jKCdwbmcnLCAncGRmJyl9CnJsZCA8LSBsb2cyKG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9GV19DbGFkZTFfc2lnKzEpCmdlbmVEaXN0cyA8LSBkaXN0KG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9GV19DbGFkZTFfc2lnKQpkZiA8LSBkYXRhLmZyYW1lKHBoLGNsLCBjb25kaXRpb24sc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKcm93bmFtZXMoZGYpIDwtIGNvbG5hbWVzKHJsZCkKcGhlYXRtYXAocmxkLCBzaG93X3Jvd25hbWVzPUZBTFNFLAogICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX3Jvd3MgPSBnZW5lRGlzdHMsIGNsdXN0ZXJfY29scz0gRkFMU0UsYW5ub3RhdGlvbl9jb2w9ZGYpCmBgYAoKIyMgTWFyaW5lLUNsYWRlIDIgKHRocmVlLXdheSkgcmVzcG9uc2UKCmBgYHtyIE1DbGFkZTIsIGZpZy5rZWVwPSJsYXN0IiwgZmlnLndpZHRoPTExLCBmaWcucGF0aD0nZmlndXJlcy8nLCBkZXY9YygncG5nJywgJ3BkZicpfQpybGQgPC0gbG9nMihtZWFuX25vcm1fY291bnRzX29yZGVyZWRfTV9DbGFkZTJfc2lnKzEpCmdlbmVEaXN0cyA8LSBkaXN0KG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9NX0NsYWRlMl9zaWcpCmRmIDwtIGRhdGEuZnJhbWUocGgsY2wsIGNvbmRpdGlvbixzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQpyb3duYW1lcyhkZikgPC0gY29sbmFtZXMocmxkKQpwaGVhdG1hcChybGQsIHNob3dfcm93bmFtZXM9RkFMU0UsCiAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9IGdlbmVEaXN0cywgY2x1c3Rlcl9jb2xzPSBGQUxTRSxhbm5vdGF0aW9uX2NvbD1kZikKYGBgCgojIyBGcmVzaHdhdGVyLUNsYWRlIDIgKHRocmVlLXdheSkgcmVzcG9uc2UKCmBgYHtyIEZXQ2xhZGUyLCBmaWcua2VlcD0ibGFzdCIsIGZpZy53aWR0aD0xMSwgZmlnLnBhdGg9J2ZpZ3VyZXMvJywgZGV2PWMoJ3BuZycsICdwZGYnKX0KcmxkIDwtIGxvZzIobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkX0ZXX0NsYWRlMl9zaWcrMSkKZ2VuZURpc3RzIDwtIGRpc3QobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkX0ZXX0NsYWRlMl9zaWcpCmRmIDwtIGRhdGEuZnJhbWUocGgsY2wsIGNvbmRpdGlvbixzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQpyb3duYW1lcyhkZikgPC0gY29sbmFtZXMocmxkKQpwaGVhdG1hcChybGQsIHNob3dfcm93bmFtZXM9RkFMU0UsCiAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9IGdlbmVEaXN0cywgY2x1c3Rlcl9jb2xzPSBGQUxTRSxhbm5vdGF0aW9uX2NvbD1kZikKYGBgCgojIyBNYXJpbmUtQ2xhZGUgMyAodGhyZWUtd2F5KSByZXNwb25zZQoKYGBge3IgTUNsYWRlMywgZmlnLmtlZXA9Imxhc3QiLCBmaWcud2lkdGg9MTEsIGZpZy5wYXRoPSdmaWd1cmVzLycsIGRldj1jKCdwbmcnLCAncGRmJyl9CnJsZCA8LSBsb2cyKG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9NX0NsYWRlM19zaWcrMSkKZ2VuZURpc3RzIDwtIGRpc3QobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkX01fQ2xhZGUzX3NpZykKZGYgPC0gZGF0YS5mcmFtZShwaCxjbCwgY29uZGl0aW9uLHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCnJvd25hbWVzKGRmKSA8LSBjb2xuYW1lcyhybGQpCnBoZWF0bWFwKHJsZCwgc2hvd19yb3duYW1lcz1GQUxTRSwKICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9yb3dzID0gZ2VuZURpc3RzLCBjbHVzdGVyX2NvbHM9IEZBTFNFLGFubm90YXRpb25fY29sPWRmKQpgYGAKCiMjIEZyZXNod2F0ZXItQ2xhZGUgMyAodGhyZWUtd2F5KSByZXNwb25zZQoKYGBge3IgRldDbGFkZTMsIGZpZy5rZWVwPSJsYXN0IiwgZmlnLndpZHRoPTExLCBmaWcucGF0aD0nZmlndXJlcy8nLCBkZXY9YygncG5nJywgJ3BkZicpfQpybGQgPC0gbG9nMihtZWFuX25vcm1fY291bnRzX29yZGVyZWRfRldfQ2xhZGUzX3NpZysxKQpnZW5lRGlzdHMgPC0gZGlzdChtZWFuX25vcm1fY291bnRzX29yZGVyZWRfRldfQ2xhZGUzX3NpZykKZGYgPC0gZGF0YS5mcmFtZShwaCxjbCwgY29uZGl0aW9uLHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCnJvd25hbWVzKGRmKSA8LSBjb2xuYW1lcyhybGQpCnBoZWF0bWFwKHJsZCwgc2hvd19yb3duYW1lcz1GQUxTRSwKICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9yb3dzID0gZ2VuZURpc3RzLCBjbHVzdGVyX2NvbHM9IEZBTFNFLGFubm90YXRpb25fY29sPWRmKQpgYGAKCiMjIyBNYXJpbmUgcGh5c2lvbG9neSAodHdvLXdheSkgY29uc2VydmVkIHJlc3BvbnNlCgpgYGB7ciBNaGVhdG1hcCwgZmlnLmtlZXA9Imxhc3QiLCBmaWcud2lkdGg9MTEsIGZpZy5wYXRoPSdmaWd1cmVzLycsIGRldj1jKCdwbmcnLCAncGRmJyl9CnJsZCA8LSBsb2cyKG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9NX3NpZysxKQpnZW5lRGlzdHMgPC0gZGlzdChtZWFuX25vcm1fY291bnRzX29yZGVyZWRfTV9zaWcpCmRmIDwtIGRhdGEuZnJhbWUocGgsY2wsIGNvbmRpdGlvbixzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQpyb3duYW1lcyhkZikgPC0gY29sbmFtZXMocmxkKQpwaGVhdG1hcChybGQsIHNob3dfcm93bmFtZXM9RkFMU0UsCiAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9IGdlbmVEaXN0cywgY2x1c3Rlcl9jb2xzPSBGQUxTRSxhbm5vdGF0aW9uX2NvbD1kZikKYGBgCgojIyMgRnJlc2h3YXRlciBwaHlzaW9sb2d5ICh0d28td2F5KSBjb25zZXJ2ZWQgcmVzcG9uc2UKCmBgYHtyIEZXaGVhdG1hcCwgZmlnLmtlZXA9Imxhc3QiLCBmaWcud2lkdGg9MTEsIGZpZy5wYXRoPSdmaWd1cmVzLycsIGRldj1jKCdwbmcnLCAncGRmJyl9CnJsZCA8LSBsb2cyKG1lYW5fbm9ybV9jb3VudHNfb3JkZXJlZF9GV19zaWcrMSkKZ2VuZURpc3RzIDwtIGRpc3QobWVhbl9ub3JtX2NvdW50c19vcmRlcmVkX0ZXX3NpZykKZGYgPC0gZGF0YS5mcmFtZShwaCxjbCwgY29uZGl0aW9uLHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCnJvd25hbWVzKGRmKSA8LSBjb2xuYW1lcyhybGQpCnBoZWF0bWFwKHJsZCwgc2hvd19yb3duYW1lcz1GQUxTRSwKICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9yb3dzID0gZ2VuZURpc3RzLCBjbHVzdGVyX2NvbHM9IEZBTFNFLGFubm90YXRpb25fY29sPWRmKQpgYGAKCmBgYHtyIHBhY2thZ2VzfQoKc2Vzc2lvbkluZm8oKQoKYGBg